From 7634f741d944dcd45fb83f0dfd594ecda49d2bfd Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 09:06:40 -0800 Subject: [PATCH 01/41] Conformance tests for array element type of tuple is union type of tuple element types --- .../reference/castingTuple.errors.txt | 19 ++-- tests/baselines/reference/castingTuple.js | 15 +++- .../contextualTypeWithTuple.errors.txt | 37 ++++++-- .../reference/contextualTypeWithTuple.js | 31 ++++++- tests/baselines/reference/indexerWithTuple.js | 49 ++++++++-- .../reference/indexerWithTuple.types | 90 ++++++++++++++++++- .../conformance/types/tuple/castingTuple.ts | 8 +- .../types/tuple/contextualTypeWithTuple.ts | 12 +++ .../types/tuple/indexerWithTuple.ts | 25 +++++- 9 files changed, 251 insertions(+), 35 deletions(-) diff --git a/tests/baselines/reference/castingTuple.errors.txt b/tests/baselines/reference/castingTuple.errors.txt index f4efed6f1d1..98be259964d 100644 --- a/tests/baselines/reference/castingTuple.errors.txt +++ b/tests/baselines/reference/castingTuple.errors.txt @@ -2,19 +2,19 @@ tests/cases/conformance/types/tuple/castingTuple.ts(13,23): error TS2352: Neithe Property '2' is missing in type '[number, string]'. tests/cases/conformance/types/tuple/castingTuple.ts(16,21): error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other. Property '2' is missing in type '[C, D]'. -tests/cases/conformance/types/tuple/castingTuple.ts(24,10): error TS2352: Neither type '[number, string]' nor type '[number, number]' is assignable to the other. +tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Neither type '[number, string]' nor type '[number, number]' is assignable to the other. Types of property '1' are incompatible. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/tuple/castingTuple.ts(25,10): error TS2352: Neither type '[C, D]' nor type '[A, I]' is assignable to the other. +tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Neither type '[C, D]' nor type '[A, I]' is assignable to the other. Types of property '0' are incompatible. Type 'C' is not assignable to type 'A'. -tests/cases/conformance/types/tuple/castingTuple.ts(26,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. -tests/cases/conformance/types/tuple/castingTuple.ts(26,14): error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other. +tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. +tests/cases/conformance/types/tuple/castingTuple.ts(30,14): error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other. Types of property 'pop' are incompatible. Type '() => string | number' is not assignable to type '() => number'. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/tuple/castingTuple.ts(27,1): error TS2304: Cannot find name 't4'. +tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'. ==== tests/cases/conformance/types/tuple/castingTuple.ts (7 errors) ==== @@ -41,10 +41,14 @@ tests/cases/conformance/types/tuple/castingTuple.ts(27,1): error TS2304: Cannot !!! error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other. !!! error TS2352: Property '2' is missing in type '[C, D]'. var eleFromCDA1 = classCDATuple[2]; // A - var eleFromCDA2 = classCDATuple[5]; // {} + var eleFromCDA2 = classCDATuple[5]; // C | D | A var t10: [E1, E2] = [E1.one, E2.one]; var t11 = <[number, number]>t10; var array1 = <{}[]>emptyObjTuple; + var unionTuple: [C, string | number] = [new C(), "foo"]; + var unionTuple2: [C, string | number, D] = [new C(), "foo", new D()]; + var unionTuple3: [number, string| number] = [10, "foo"]; + var unionTuple4 = <[number, number]>unionTuple3; // error var t3 = <[number, number]>numStrTuple; @@ -68,4 +72,5 @@ tests/cases/conformance/types/tuple/castingTuple.ts(27,1): error TS2304: Cannot !!! error TS2352: Type 'string' is not assignable to type 'number'. t4[2] = 10; ~~ -!!! error TS2304: Cannot find name 't4'. \ No newline at end of file +!!! error TS2304: Cannot find name 't4'. + \ No newline at end of file diff --git a/tests/baselines/reference/castingTuple.js b/tests/baselines/reference/castingTuple.js index 0671062bb4e..fffadcbc070 100644 --- a/tests/baselines/reference/castingTuple.js +++ b/tests/baselines/reference/castingTuple.js @@ -16,16 +16,21 @@ var classCDTuple: [C, D] = [new C(), new D()]; var interfaceIITuple = <[I, I]>classCDTuple; var classCDATuple = <[C, D, A]>classCDTuple; var eleFromCDA1 = classCDATuple[2]; // A -var eleFromCDA2 = classCDATuple[5]; // {} +var eleFromCDA2 = classCDATuple[5]; // C | D | A var t10: [E1, E2] = [E1.one, E2.one]; var t11 = <[number, number]>t10; var array1 = <{}[]>emptyObjTuple; +var unionTuple: [C, string | number] = [new C(), "foo"]; +var unionTuple2: [C, string | number, D] = [new C(), "foo", new D()]; +var unionTuple3: [number, string| number] = [10, "foo"]; +var unionTuple4 = <[number, number]>unionTuple3; // error var t3 = <[number, number]>numStrTuple; var t9 = <[A, I]>classCDTuple; var array1 = numStrTuple; -t4[2] = 10; +t4[2] = 10; + //// [castingTuple.js] var __extends = this.__extends || function (d, b) { @@ -84,10 +89,14 @@ var classCDTuple = [new C(), new D()]; var interfaceIITuple = classCDTuple; var classCDATuple = classCDTuple; var eleFromCDA1 = classCDATuple[2]; // A -var eleFromCDA2 = classCDATuple[5]; // {} +var eleFromCDA2 = classCDATuple[5]; // C | D | A var t10 = [0 /* one */, 0 /* one */]; var t11 = t10; var array1 = emptyObjTuple; +var unionTuple = [new C(), "foo"]; +var unionTuple2 = [new C(), "foo", new D()]; +var unionTuple3 = [10, "foo"]; +var unionTuple4 = unionTuple3; // error var t3 = numStrTuple; var t9 = classCDTuple; diff --git a/tests/baselines/reference/contextualTypeWithTuple.errors.txt b/tests/baselines/reference/contextualTypeWithTuple.errors.txt index d093e176455..32e368b0f88 100644 --- a/tests/baselines/reference/contextualTypeWithTuple.errors.txt +++ b/tests/baselines/reference/contextualTypeWithTuple.errors.txt @@ -4,21 +4,27 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(3,5): error TS232 Type 'string | number | boolean' is not assignable to type 'string | number'. Type 'boolean' is not assignable to type 'string | number'. Type 'boolean' is not assignable to type 'number'. -tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(8,1): error TS2323: Type '[number, string, boolean]' is not assignable to type '[number, string]'. -tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(11,1): error TS2323: Type '[{}, number]' is not assignable to type '[{ a: string; }, number]'. +tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(15,1): error TS2323: Type '[number, string, boolean]' is not assignable to type '[number, string]'. +tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(18,1): error TS2323: Type '[{}, number]' is not assignable to type '[{ a: string; }, number]'. Types of property '0' are incompatible. Type '{}' is not assignable to type '{ a: string; }'. Property 'a' is missing in type '{}'. -tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(12,1): error TS2323: Type '[number, string]' is not assignable to type '[number, string, boolean]'. +tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(19,1): error TS2323: Type '[number, string]' is not assignable to type '[number, string, boolean]'. Property '2' is missing in type '[number, string]'. -tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(13,5): error TS2323: Type '[string, string, number]' is not assignable to type '[string, string]'. +tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(20,5): error TS2323: Type '[string, string, number]' is not assignable to type '[string, string]'. Types of property 'pop' are incompatible. Type '() => string | number' is not assignable to type '() => string'. Type 'string | number' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(24,1): error TS2323: Type '[C, string | number]' is not assignable to type '[C, string | number, D]'. + Property '2' is missing in type '[C, string | number]'. +tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS2323: Type '[number, string | number]' is not assignable to type '[number, string]'. + Types of property '1' are incompatible. + Type 'string | number' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. -==== tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts (5 errors) ==== +==== tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts (7 errors) ==== // no error var numStrTuple: [number, string] = [5, "hello"]; var numStrTuple2: [number, string] = [5, "foo", true]; @@ -32,6 +38,13 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(13,5): error TS23 var numStrBoolTuple: [number, string, boolean] = [5, "foo", true]; var objNumTuple: [{ a: string }, number] = [{ a: "world" }, 5]; var strTupleTuple: [string, [number, {}]] = ["bar", [5, { x: 1, y: 1 }]]; + class C { } + class D { } + var unionTuple: [C, string | number] = [new C(), "foo"]; + var unionTuple1: [C, string | number] = [new C(), "foo"]; + var unionTuple2: [C, string | number, D] = [new C(), "foo", new D()]; + var unionTuple3: [number, string| number] = [10, "foo"]; + numStrTuple = numStrTuple2; numStrTuple = numStrBoolTuple; ~~~~~~~~~~~ @@ -55,4 +68,16 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(13,5): error TS23 !!! error TS2323: Type '() => string | number' is not assignable to type '() => string'. !!! error TS2323: Type 'string | number' is not assignable to type 'string'. !!! error TS2323: Type 'number' is not assignable to type 'string'. - \ No newline at end of file + + unionTuple = unionTuple1; + unionTuple = unionTuple2; + unionTuple2 = unionTuple; + ~~~~~~~~~~~ +!!! error TS2323: Type '[C, string | number]' is not assignable to type '[C, string | number, D]'. +!!! error TS2323: Property '2' is missing in type '[C, string | number]'. + numStrTuple = unionTuple3; + ~~~~~~~~~~~ +!!! error TS2323: Type '[number, string | number]' is not assignable to type '[number, string]'. +!!! error TS2323: Types of property '1' are incompatible. +!!! error TS2323: Type 'string | number' is not assignable to type 'string'. +!!! error TS2323: Type 'number' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeWithTuple.js b/tests/baselines/reference/contextualTypeWithTuple.js index 61a2df5d8ce..cfcdd13f7d0 100644 --- a/tests/baselines/reference/contextualTypeWithTuple.js +++ b/tests/baselines/reference/contextualTypeWithTuple.js @@ -5,6 +5,13 @@ var numStrTuple2: [number, string] = [5, "foo", true]; var numStrBoolTuple: [number, string, boolean] = [5, "foo", true]; var objNumTuple: [{ a: string }, number] = [{ a: "world" }, 5]; var strTupleTuple: [string, [number, {}]] = ["bar", [5, { x: 1, y: 1 }]]; +class C { } +class D { } +var unionTuple: [C, string | number] = [new C(), "foo"]; +var unionTuple1: [C, string | number] = [new C(), "foo"]; +var unionTuple2: [C, string | number, D] = [new C(), "foo", new D()]; +var unionTuple3: [number, string| number] = [10, "foo"]; + numStrTuple = numStrTuple2; numStrTuple = numStrBoolTuple; @@ -12,7 +19,11 @@ numStrTuple = numStrBoolTuple; objNumTuple = [ {}, 5]; numStrBoolTuple = numStrTuple; var strStrTuple: [string, string] = ["foo", "bar", 5]; - + +unionTuple = unionTuple1; +unionTuple = unionTuple2; +unionTuple2 = unionTuple; +numStrTuple = unionTuple3; //// [contextualTypeWithTuple.js] // no error @@ -21,9 +32,27 @@ var numStrTuple2 = [5, "foo", true]; var numStrBoolTuple = [5, "foo", true]; var objNumTuple = [{ a: "world" }, 5]; var strTupleTuple = ["bar", [5, { x: 1, y: 1 }]]; +var C = (function () { + function C() { + } + return C; +})(); +var D = (function () { + function D() { + } + return D; +})(); +var unionTuple = [new C(), "foo"]; +var unionTuple1 = [new C(), "foo"]; +var unionTuple2 = [new C(), "foo", new D()]; +var unionTuple3 = [10, "foo"]; numStrTuple = numStrTuple2; numStrTuple = numStrBoolTuple; // error objNumTuple = [{}, 5]; numStrBoolTuple = numStrTuple; var strStrTuple = ["foo", "bar", 5]; +unionTuple = unionTuple1; +unionTuple = unionTuple2; +unionTuple2 = unionTuple; +numStrTuple = unionTuple3; diff --git a/tests/baselines/reference/indexerWithTuple.js b/tests/baselines/reference/indexerWithTuple.js index fc82716ba05..91d90792e6d 100644 --- a/tests/baselines/reference/indexerWithTuple.js +++ b/tests/baselines/reference/indexerWithTuple.js @@ -1,32 +1,65 @@ //// [indexerWithTuple.ts] var strNumTuple: [string, number] = ["foo", 10]; var numTupleTuple: [number, [string, number]] = [10, ["bar", 20]]; +var unionTuple1: [number, string| number] = [10, "foo"]; +var unionTuple2: [boolean, string| number] = [true, "foo"]; // no error var idx0 = 0; var idx1 = 1; var ele10 = strNumTuple[0]; // string var ele11 = strNumTuple[1]; // number -var ele12 = strNumTuple[2]; // {} -var ele13 = strNumTuple[idx0]; // {} -var ele14 = strNumTuple[idx1]; // {} +var ele12 = strNumTuple[2]; // string | number +var ele13 = strNumTuple[idx0]; // string | number +var ele14 = strNumTuple[idx1]; // string | number var ele15 = strNumTuple["0"]; // string var ele16 = strNumTuple["1"]; // number var strNumTuple1 = numTupleTuple[1]; //[string, number]; -var ele17 = numTupleTuple[2]; // {} +var ele17 = numTupleTuple[2]; // number | [string, number] +var eleUnion10 = unionTuple1[0]; // number +var eleUnion11 = unionTuple1[1]; // string | number +var eleUnion12 = unionTuple1[2]; // string | number +var eleUnion13 = unionTuple1[idx0]; // string | number +var eleUnion14 = unionTuple1[idx1]; // string | number +var eleUnion15 = unionTuple1["0"]; // number +var eleUnion16 = unionTuple1["1"]; // string | number + +var eleUnion20 = unionTuple2[0]; // boolean +var eleUnion21 = unionTuple2[1]; // string | number +var eleUnion22 = unionTuple2[2]; // string | number | boolean +var eleUnion23 = unionTuple2[idx0]; // string | number | boolean +var eleUnion24 = unionTuple2[idx1]; // string | number | boolean +var eleUnion25 = unionTuple2["0"]; // boolean +var eleUnion26 = unionTuple2["1"]; // string | number //// [indexerWithTuple.js] var strNumTuple = ["foo", 10]; var numTupleTuple = [10, ["bar", 20]]; +var unionTuple1 = [10, "foo"]; +var unionTuple2 = [true, "foo"]; // no error var idx0 = 0; var idx1 = 1; var ele10 = strNumTuple[0]; // string var ele11 = strNumTuple[1]; // number -var ele12 = strNumTuple[2]; // {} -var ele13 = strNumTuple[idx0]; // {} -var ele14 = strNumTuple[idx1]; // {} +var ele12 = strNumTuple[2]; // string | number +var ele13 = strNumTuple[idx0]; // string | number +var ele14 = strNumTuple[idx1]; // string | number var ele15 = strNumTuple["0"]; // string var ele16 = strNumTuple["1"]; // number var strNumTuple1 = numTupleTuple[1]; //[string, number]; -var ele17 = numTupleTuple[2]; // {} +var ele17 = numTupleTuple[2]; // number | [string, number] +var eleUnion10 = unionTuple1[0]; // number +var eleUnion11 = unionTuple1[1]; // string | number +var eleUnion12 = unionTuple1[2]; // string | number +var eleUnion13 = unionTuple1[idx0]; // string | number +var eleUnion14 = unionTuple1[idx1]; // string | number +var eleUnion15 = unionTuple1["0"]; // number +var eleUnion16 = unionTuple1["1"]; // string | number +var eleUnion20 = unionTuple2[0]; // boolean +var eleUnion21 = unionTuple2[1]; // string | number +var eleUnion22 = unionTuple2[2]; // string | number | boolean +var eleUnion23 = unionTuple2[idx0]; // string | number | boolean +var eleUnion24 = unionTuple2[idx1]; // string | number | boolean +var eleUnion25 = unionTuple2["0"]; // boolean +var eleUnion26 = unionTuple2["1"]; // string | number diff --git a/tests/baselines/reference/indexerWithTuple.types b/tests/baselines/reference/indexerWithTuple.types index 28053a33081..75b89ca6088 100644 --- a/tests/baselines/reference/indexerWithTuple.types +++ b/tests/baselines/reference/indexerWithTuple.types @@ -8,6 +8,14 @@ var numTupleTuple: [number, [string, number]] = [10, ["bar", 20]]; >[10, ["bar", 20]] : [number, [string, number]] >["bar", 20] : [string, number] +var unionTuple1: [number, string| number] = [10, "foo"]; +>unionTuple1 : [number, string | number] +>[10, "foo"] : [number, string] + +var unionTuple2: [boolean, string| number] = [true, "foo"]; +>unionTuple2 : [boolean, string | number] +>[true, "foo"] : [boolean, string] + // no error var idx0 = 0; >idx0 : number @@ -25,18 +33,18 @@ var ele11 = strNumTuple[1]; // number >strNumTuple[1] : number >strNumTuple : [string, number] -var ele12 = strNumTuple[2]; // {} +var ele12 = strNumTuple[2]; // string | number >ele12 : string | number >strNumTuple[2] : string | number >strNumTuple : [string, number] -var ele13 = strNumTuple[idx0]; // {} +var ele13 = strNumTuple[idx0]; // string | number >ele13 : string | number >strNumTuple[idx0] : string | number >strNumTuple : [string, number] >idx0 : number -var ele14 = strNumTuple[idx1]; // {} +var ele14 = strNumTuple[idx1]; // string | number >ele14 : string | number >strNumTuple[idx1] : string | number >strNumTuple : [string, number] @@ -57,8 +65,82 @@ var strNumTuple1 = numTupleTuple[1]; //[string, number]; >numTupleTuple[1] : [string, number] >numTupleTuple : [number, [string, number]] -var ele17 = numTupleTuple[2]; // {} +var ele17 = numTupleTuple[2]; // number | [string, number] >ele17 : number | [string, number] >numTupleTuple[2] : number | [string, number] >numTupleTuple : [number, [string, number]] +var eleUnion10 = unionTuple1[0]; // number +>eleUnion10 : number +>unionTuple1[0] : number +>unionTuple1 : [number, string | number] + +var eleUnion11 = unionTuple1[1]; // string | number +>eleUnion11 : string | number +>unionTuple1[1] : string | number +>unionTuple1 : [number, string | number] + +var eleUnion12 = unionTuple1[2]; // string | number +>eleUnion12 : string | number +>unionTuple1[2] : string | number +>unionTuple1 : [number, string | number] + +var eleUnion13 = unionTuple1[idx0]; // string | number +>eleUnion13 : string | number +>unionTuple1[idx0] : string | number +>unionTuple1 : [number, string | number] +>idx0 : number + +var eleUnion14 = unionTuple1[idx1]; // string | number +>eleUnion14 : string | number +>unionTuple1[idx1] : string | number +>unionTuple1 : [number, string | number] +>idx1 : number + +var eleUnion15 = unionTuple1["0"]; // number +>eleUnion15 : number +>unionTuple1["0"] : number +>unionTuple1 : [number, string | number] + +var eleUnion16 = unionTuple1["1"]; // string | number +>eleUnion16 : string | number +>unionTuple1["1"] : string | number +>unionTuple1 : [number, string | number] + +var eleUnion20 = unionTuple2[0]; // boolean +>eleUnion20 : boolean +>unionTuple2[0] : boolean +>unionTuple2 : [boolean, string | number] + +var eleUnion21 = unionTuple2[1]; // string | number +>eleUnion21 : string | number +>unionTuple2[1] : string | number +>unionTuple2 : [boolean, string | number] + +var eleUnion22 = unionTuple2[2]; // string | number | boolean +>eleUnion22 : string | number | boolean +>unionTuple2[2] : string | number | boolean +>unionTuple2 : [boolean, string | number] + +var eleUnion23 = unionTuple2[idx0]; // string | number | boolean +>eleUnion23 : string | number | boolean +>unionTuple2[idx0] : string | number | boolean +>unionTuple2 : [boolean, string | number] +>idx0 : number + +var eleUnion24 = unionTuple2[idx1]; // string | number | boolean +>eleUnion24 : string | number | boolean +>unionTuple2[idx1] : string | number | boolean +>unionTuple2 : [boolean, string | number] +>idx1 : number + +var eleUnion25 = unionTuple2["0"]; // boolean +>eleUnion25 : boolean +>unionTuple2["0"] : boolean +>unionTuple2 : [boolean, string | number] + +var eleUnion26 = unionTuple2["1"]; // string | number +>eleUnion26 : string | number +>unionTuple2["1"] : string | number +>unionTuple2 : [boolean, string | number] + diff --git a/tests/cases/conformance/types/tuple/castingTuple.ts b/tests/cases/conformance/types/tuple/castingTuple.ts index f154e5f00c8..cf5c58af346 100644 --- a/tests/cases/conformance/types/tuple/castingTuple.ts +++ b/tests/cases/conformance/types/tuple/castingTuple.ts @@ -15,13 +15,17 @@ var classCDTuple: [C, D] = [new C(), new D()]; var interfaceIITuple = <[I, I]>classCDTuple; var classCDATuple = <[C, D, A]>classCDTuple; var eleFromCDA1 = classCDATuple[2]; // A -var eleFromCDA2 = classCDATuple[5]; // {} +var eleFromCDA2 = classCDATuple[5]; // C | D | A var t10: [E1, E2] = [E1.one, E2.one]; var t11 = <[number, number]>t10; var array1 = <{}[]>emptyObjTuple; +var unionTuple: [C, string | number] = [new C(), "foo"]; +var unionTuple2: [C, string | number, D] = [new C(), "foo", new D()]; +var unionTuple3: [number, string| number] = [10, "foo"]; +var unionTuple4 = <[number, number]>unionTuple3; // error var t3 = <[number, number]>numStrTuple; var t9 = <[A, I]>classCDTuple; var array1 = numStrTuple; -t4[2] = 10; \ No newline at end of file +t4[2] = 10; diff --git a/tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts b/tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts index 7e9575d7f82..9600ebcd671 100644 --- a/tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts +++ b/tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts @@ -4,6 +4,13 @@ var numStrTuple2: [number, string] = [5, "foo", true]; var numStrBoolTuple: [number, string, boolean] = [5, "foo", true]; var objNumTuple: [{ a: string }, number] = [{ a: "world" }, 5]; var strTupleTuple: [string, [number, {}]] = ["bar", [5, { x: 1, y: 1 }]]; +class C { } +class D { } +var unionTuple: [C, string | number] = [new C(), "foo"]; +var unionTuple1: [C, string | number] = [new C(), "foo"]; +var unionTuple2: [C, string | number, D] = [new C(), "foo", new D()]; +var unionTuple3: [number, string| number] = [10, "foo"]; + numStrTuple = numStrTuple2; numStrTuple = numStrBoolTuple; @@ -11,3 +18,8 @@ numStrTuple = numStrBoolTuple; objNumTuple = [ {}, 5]; numStrBoolTuple = numStrTuple; var strStrTuple: [string, string] = ["foo", "bar", 5]; + +unionTuple = unionTuple1; +unionTuple = unionTuple2; +unionTuple2 = unionTuple; +numStrTuple = unionTuple3; \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/indexerWithTuple.ts b/tests/cases/conformance/types/tuple/indexerWithTuple.ts index 0b51ecd32ee..930ca56402c 100644 --- a/tests/cases/conformance/types/tuple/indexerWithTuple.ts +++ b/tests/cases/conformance/types/tuple/indexerWithTuple.ts @@ -1,15 +1,32 @@ var strNumTuple: [string, number] = ["foo", 10]; var numTupleTuple: [number, [string, number]] = [10, ["bar", 20]]; +var unionTuple1: [number, string| number] = [10, "foo"]; +var unionTuple2: [boolean, string| number] = [true, "foo"]; // no error var idx0 = 0; var idx1 = 1; var ele10 = strNumTuple[0]; // string var ele11 = strNumTuple[1]; // number -var ele12 = strNumTuple[2]; // {} -var ele13 = strNumTuple[idx0]; // {} -var ele14 = strNumTuple[idx1]; // {} +var ele12 = strNumTuple[2]; // string | number +var ele13 = strNumTuple[idx0]; // string | number +var ele14 = strNumTuple[idx1]; // string | number var ele15 = strNumTuple["0"]; // string var ele16 = strNumTuple["1"]; // number var strNumTuple1 = numTupleTuple[1]; //[string, number]; -var ele17 = numTupleTuple[2]; // {} \ No newline at end of file +var ele17 = numTupleTuple[2]; // number | [string, number] +var eleUnion10 = unionTuple1[0]; // number +var eleUnion11 = unionTuple1[1]; // string | number +var eleUnion12 = unionTuple1[2]; // string | number +var eleUnion13 = unionTuple1[idx0]; // string | number +var eleUnion14 = unionTuple1[idx1]; // string | number +var eleUnion15 = unionTuple1["0"]; // number +var eleUnion16 = unionTuple1["1"]; // string | number + +var eleUnion20 = unionTuple2[0]; // boolean +var eleUnion21 = unionTuple2[1]; // string | number +var eleUnion22 = unionTuple2[2]; // string | number | boolean +var eleUnion23 = unionTuple2[idx0]; // string | number | boolean +var eleUnion24 = unionTuple2[idx1]; // string | number | boolean +var eleUnion25 = unionTuple2["0"]; // boolean +var eleUnion26 = unionTuple2["1"]; // string | number \ No newline at end of file From 568049474e3980751376f8b620dfef711ed65c1f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 09:20:20 -0800 Subject: [PATCH 02/41] =?UTF-8?q?Tests=20to=20check=20equivalency=20of=20u?= =?UTF-8?q?nion=20types=20A=20union=20type=20encompasses=20an=20unordered?= =?UTF-8?q?=20set=20of=20unrelated=20types=20(that=20is,=20types=20that=20?= =?UTF-8?q?aren=E2=80=99t=20subtypes=20of=20each=20other).=20The=20followi?= =?UTF-8?q?ng=20rules=20govern=20union=20types:=20=E2=80=A2=09A=20|=20B=20?= =?UTF-8?q?is=20equivalent=20to=20A=20if=20B=20is=20a=20subtype=20of=20A.?= =?UTF-8?q?=20=E2=80=A2=09A=20|=20B=20is=20equivalent=20to=20B=20|=20A.=20?= =?UTF-8?q?=E2=80=A2=09AB=20|=20C=20is=20equivalent=20to=20A=20|=20BC,=20w?= =?UTF-8?q?here=20AB=20is=20A=20|=20B=20and=20BC=20is=20B=20|=20C.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/unionTypeEquivalence.js | 54 +++++++++++++++++++ .../reference/unionTypeEquivalence.types | 49 +++++++++++++++++ .../types/union/unionTypeEquivalence.ts | 18 +++++++ 3 files changed, 121 insertions(+) create mode 100644 tests/baselines/reference/unionTypeEquivalence.js create mode 100644 tests/baselines/reference/unionTypeEquivalence.types create mode 100644 tests/cases/conformance/types/union/unionTypeEquivalence.ts diff --git a/tests/baselines/reference/unionTypeEquivalence.js b/tests/baselines/reference/unionTypeEquivalence.js new file mode 100644 index 00000000000..3698ecd2f92 --- /dev/null +++ b/tests/baselines/reference/unionTypeEquivalence.js @@ -0,0 +1,54 @@ +//// [unionTypeEquivalence.ts] +// A | B is equivalent to A if B is a subtype of A +class C { } +class D extends C { } +var x: C; +var x : C | D; + +// A | B is equivalent to B | A. +var y: string | number; +var y : number | string; + +// AB | C is equivalent to A | BC, where AB is A | B and BC is B | C. +var z : string | number | boolean; +var z : (string | number) | boolean; +var z : string | (number | boolean); +var AB : string | number; +var BC : number | boolean; +var z1: typeof AB | boolean; +var z1: string | typeof BC; + + +//// [unionTypeEquivalence.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +// A | B is equivalent to A if B is a subtype of A +var C = (function () { + function C() { + } + return C; +})(); +var D = (function (_super) { + __extends(D, _super); + function D() { + _super.apply(this, arguments); + } + return D; +})(C); +var x; +var x; +// A | B is equivalent to B | A. +var y; +var y; +// AB | C is equivalent to A | BC, where AB is A | B and BC is B | C. +var z; +var z; +var z; +var AB; +var BC; +var z1; +var z1; diff --git a/tests/baselines/reference/unionTypeEquivalence.types b/tests/baselines/reference/unionTypeEquivalence.types new file mode 100644 index 00000000000..53e95659120 --- /dev/null +++ b/tests/baselines/reference/unionTypeEquivalence.types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/types/union/unionTypeEquivalence.ts === +// A | B is equivalent to A if B is a subtype of A +class C { } +>C : C + +class D extends C { } +>D : D +>C : C + +var x: C; +>x : C +>C : C + +var x : C | D; +>x : C +>C : C +>D : D + +// A | B is equivalent to B | A. +var y: string | number; +>y : string | number + +var y : number | string; +>y : string | number + +// AB | C is equivalent to A | BC, where AB is A | B and BC is B | C. +var z : string | number | boolean; +>z : string | number | boolean + +var z : (string | number) | boolean; +>z : string | number | boolean + +var z : string | (number | boolean); +>z : string | number | boolean + +var AB : string | number; +>AB : string | number + +var BC : number | boolean; +>BC : number | boolean + +var z1: typeof AB | boolean; +>z1 : string | number | boolean +>AB : string | number + +var z1: string | typeof BC; +>z1 : string | number | boolean +>BC : number | boolean + diff --git a/tests/cases/conformance/types/union/unionTypeEquivalence.ts b/tests/cases/conformance/types/union/unionTypeEquivalence.ts new file mode 100644 index 00000000000..0905fde17f8 --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeEquivalence.ts @@ -0,0 +1,18 @@ +// A | B is equivalent to A if B is a subtype of A +class C { } +class D extends C { } +var x: C; +var x : C | D; + +// A | B is equivalent to B | A. +var y: string | number; +var y : number | string; + +// AB | C is equivalent to A | BC, where AB is A | B and BC is B | C. +var z : string | number | boolean; +var z : (string | number) | boolean; +var z : string | (number | boolean); +var AB : string | number; +var BC : number | boolean; +var z1: typeof AB | boolean; +var z1: string | typeof BC; From a1535533e7da2e8688c5f3f4b6cbc979633e5ecf Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 09:30:49 -0800 Subject: [PATCH 03/41] Tests for source (S) of subtype is union type (U) A union type U is a subtype of a type T if each type in U is a subtype of T --- ...IfEveryConstituentTypeIsSubtype.errors.txt | 239 ++++++++++++++++++ ...nSubtypeIfEveryConstituentTypeIsSubtype.js | 180 +++++++++++++ ...nSubtypeIfEveryConstituentTypeIsSubtype.ts | 143 +++++++++++ 3 files changed, 562 insertions(+) create mode 100644 tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.errors.txt create mode 100644 tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.js create mode 100644 tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts diff --git a/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.errors.txt b/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.errors.txt new file mode 100644 index 00000000000..013b5d9a990 --- /dev/null +++ b/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.errors.txt @@ -0,0 +1,239 @@ +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(15,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(21,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'string'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(22,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'string'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(28,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'boolean'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(29,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'boolean'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(35,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'Date'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(36,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'Date'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(42,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'RegExp'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(43,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'RegExp'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(49,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '{ bar: number; }'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(50,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '{ bar: number; }'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(56,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'number[]'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(57,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'number[]'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(63,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'I8'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(64,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'I8'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(70,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'A'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(71,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'A'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(77,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'A2'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(78,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'A2'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(84,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '(x: any) => number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(85,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '(x: any) => number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(91,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '(x: T) => T'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(92,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '(x: T) => T'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(99,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'E2'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(100,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'E2'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(110,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'typeof f'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(111,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'typeof f'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(121,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'typeof c'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(122,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'typeof c'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(128,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'T'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(129,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'T'. + + +==== tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts (31 errors) ==== + enum e { + e1, + e2 + } + + // A union type U is a subtype of a type T if each type in U is a subtype of T + interface I { + [x: string]: any; + foo: string | number; // ok + foo2: e | number; // ok + } + interface I2 { + [x: string]: number; + // S is union type and each constituent type of S is a subtype of T + foo: string | number; // error string is not subtype of number + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'number'. + foo2: e | number; // ok e and number both subtype of number + } + + interface I3 { + [x: string]: string; + foo: string | number; // error numer is not subtype of string + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'string'. + foo2: e | number; // error e and number both not subtype of string + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'string'. + } + + // error cases + interface I4 { + [x: string]: boolean; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'boolean'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'boolean'. + } + + + interface I5 { + [x: string]: Date; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'Date'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'Date'. + } + + + interface I6 { + [x: string]: RegExp; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'RegExp'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'RegExp'. + } + + + interface I7 { + [x: string]: { bar: number }; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '{ bar: number; }'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '{ bar: number; }'. + } + + + interface I8 { + [x: string]: number[]; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'number[]'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'number[]'. + } + + + interface I9 { + [x: string]: I8; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'I8'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'I8'. + } + + class A { foo: number; } + interface I10 { + [x: string]: A; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'A'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'A'. + } + + class A2 { foo: T; } + interface I11 { + [x: string]: A2; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'A2'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'A2'. + } + + + interface I12 { + [x: string]: (x) => number; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '(x: any) => number'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '(x: any) => number'. + } + + + interface I13 { + [x: string]: (x: T) => T; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '(x: T) => T'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '(x: T) => T'. + } + + + enum E2 { A } + interface I14 { + [x: string]: E2; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'E2'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'E2'. + } + + + function f() { } + module f { + export var bar = 1; + } + interface I15 { + [x: string]: typeof f; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'typeof f'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'typeof f'. + } + + + class c { baz: string } + module c { + export var bar = 1; + } + interface I16 { + [x: string]: typeof c; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'typeof c'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'typeof c'. + } + + + interface I17 { + [x: string]: T; + foo: string | number; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'T'. + foo2: e | number; + ~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'T'. + } + + interface I19 { + [x: string]: Object; + foo: string | number; + foo2: e | number; + } + + + interface I20 { + [x: string]: {}; + foo: string | number; + foo2: e | number; + } \ No newline at end of file diff --git a/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.js b/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.js new file mode 100644 index 00000000000..0c9ffeb5653 --- /dev/null +++ b/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.js @@ -0,0 +1,180 @@ +//// [unionSubtypeIfEveryConstituentTypeIsSubtype.ts] +enum e { + e1, + e2 +} + +// A union type U is a subtype of a type T if each type in U is a subtype of T +interface I { + [x: string]: any; + foo: string | number; // ok + foo2: e | number; // ok +} +interface I2 { + [x: string]: number; + // S is union type and each constituent type of S is a subtype of T + foo: string | number; // error string is not subtype of number + foo2: e | number; // ok e and number both subtype of number +} + +interface I3 { + [x: string]: string; + foo: string | number; // error numer is not subtype of string + foo2: e | number; // error e and number both not subtype of string +} + +// error cases +interface I4 { + [x: string]: boolean; + foo: string | number; + foo2: e | number; +} + + +interface I5 { + [x: string]: Date; + foo: string | number; + foo2: e | number; +} + + +interface I6 { + [x: string]: RegExp; + foo: string | number; + foo2: e | number; +} + + +interface I7 { + [x: string]: { bar: number }; + foo: string | number; + foo2: e | number; +} + + +interface I8 { + [x: string]: number[]; + foo: string | number; + foo2: e | number; +} + + +interface I9 { + [x: string]: I8; + foo: string | number; + foo2: e | number; +} + +class A { foo: number; } +interface I10 { + [x: string]: A; + foo: string | number; + foo2: e | number; +} + +class A2 { foo: T; } +interface I11 { + [x: string]: A2; + foo: string | number; + foo2: e | number; +} + + +interface I12 { + [x: string]: (x) => number; + foo: string | number; + foo2: e | number; +} + + +interface I13 { + [x: string]: (x: T) => T; + foo: string | number; + foo2: e | number; +} + + +enum E2 { A } +interface I14 { + [x: string]: E2; + foo: string | number; + foo2: e | number; +} + + +function f() { } +module f { + export var bar = 1; +} +interface I15 { + [x: string]: typeof f; + foo: string | number; + foo2: e | number; +} + + +class c { baz: string } +module c { + export var bar = 1; +} +interface I16 { + [x: string]: typeof c; + foo: string | number; + foo2: e | number; +} + + +interface I17 { + [x: string]: T; + foo: string | number; + foo2: e | number; +} + +interface I19 { + [x: string]: Object; + foo: string | number; + foo2: e | number; +} + + +interface I20 { + [x: string]: {}; + foo: string | number; + foo2: e | number; +} + +//// [unionSubtypeIfEveryConstituentTypeIsSubtype.js] +var e; +(function (e) { + e[e["e1"] = 0] = "e1"; + e[e["e2"] = 1] = "e2"; +})(e || (e = {})); +var A = (function () { + function A() { + } + return A; +})(); +var A2 = (function () { + function A2() { + } + return A2; +})(); +var E2; +(function (E2) { + E2[E2["A"] = 0] = "A"; +})(E2 || (E2 = {})); +function f() { +} +var f; +(function (f) { + f.bar = 1; +})(f || (f = {})); +var c = (function () { + function c() { + } + return c; +})(); +var c; +(function (c) { + c.bar = 1; +})(c || (c = {})); diff --git a/tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts b/tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts new file mode 100644 index 00000000000..7caa26a2959 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts @@ -0,0 +1,143 @@ +enum e { + e1, + e2 +} + +// A union type U is a subtype of a type T if each type in U is a subtype of T +interface I { + [x: string]: any; + foo: string | number; // ok + foo2: e | number; // ok +} +interface I2 { + [x: string]: number; + // S is union type and each constituent type of S is a subtype of T + foo: string | number; // error string is not subtype of number + foo2: e | number; // ok e and number both subtype of number +} + +interface I3 { + [x: string]: string; + foo: string | number; // error numer is not subtype of string + foo2: e | number; // error e and number both not subtype of string +} + +// error cases +interface I4 { + [x: string]: boolean; + foo: string | number; + foo2: e | number; +} + + +interface I5 { + [x: string]: Date; + foo: string | number; + foo2: e | number; +} + + +interface I6 { + [x: string]: RegExp; + foo: string | number; + foo2: e | number; +} + + +interface I7 { + [x: string]: { bar: number }; + foo: string | number; + foo2: e | number; +} + + +interface I8 { + [x: string]: number[]; + foo: string | number; + foo2: e | number; +} + + +interface I9 { + [x: string]: I8; + foo: string | number; + foo2: e | number; +} + +class A { foo: number; } +interface I10 { + [x: string]: A; + foo: string | number; + foo2: e | number; +} + +class A2 { foo: T; } +interface I11 { + [x: string]: A2; + foo: string | number; + foo2: e | number; +} + + +interface I12 { + [x: string]: (x) => number; + foo: string | number; + foo2: e | number; +} + + +interface I13 { + [x: string]: (x: T) => T; + foo: string | number; + foo2: e | number; +} + + +enum E2 { A } +interface I14 { + [x: string]: E2; + foo: string | number; + foo2: e | number; +} + + +function f() { } +module f { + export var bar = 1; +} +interface I15 { + [x: string]: typeof f; + foo: string | number; + foo2: e | number; +} + + +class c { baz: string } +module c { + export var bar = 1; +} +interface I16 { + [x: string]: typeof c; + foo: string | number; + foo2: e | number; +} + + +interface I17 { + [x: string]: T; + foo: string | number; + foo2: e | number; +} + +interface I19 { + [x: string]: Object; + foo: string | number; + foo2: e | number; +} + + +interface I20 { + [x: string]: {}; + foo: string | number; + foo2: e | number; +} \ No newline at end of file From 703cd5d4cfed329688984c1d26ae6fc844b6cdd3 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 09:46:32 -0800 Subject: [PATCH 04/41] Tests for checking if type S is subtype of union type T is a union type and S is a subtype of at least one constituent type of T --- .../reference/subtypesOfUnion.errors.txt | 142 ++++++++++++++++++ tests/baselines/reference/subtypesOfUnion.js | 85 +++++++++++ .../subtypesAndSuperTypes/subtypesOfUnion.ts | 52 +++++++ 3 files changed, 279 insertions(+) create mode 100644 tests/baselines/reference/subtypesOfUnion.errors.txt create mode 100644 tests/baselines/reference/subtypesOfUnion.js create mode 100644 tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts diff --git a/tests/baselines/reference/subtypesOfUnion.errors.txt b/tests/baselines/reference/subtypesOfUnion.errors.txt new file mode 100644 index 00000000000..fade5377814 --- /dev/null +++ b/tests/baselines/reference/subtypesOfUnion.errors.txt @@ -0,0 +1,142 @@ +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(16,5): error TS2411: Property 'foo4' of type 'boolean' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(18,5): error TS2411: Property 'foo6' of type 'Date' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(19,5): error TS2411: Property 'foo7' of type 'RegExp' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(20,5): error TS2411: Property 'foo8' of type '{ bar: number; }' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(21,5): error TS2411: Property 'foo9' of type 'I8' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(22,5): error TS2411: Property 'foo10' of type 'A' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(23,5): error TS2411: Property 'foo11' of type 'A2' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(24,5): error TS2411: Property 'foo12' of type '(x: any) => number' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(25,5): error TS2411: Property 'foo13' of type '(x: T) => T' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(26,5): error TS2411: Property 'foo14' of type 'typeof f' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(27,5): error TS2411: Property 'foo15' of type 'typeof c' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(28,5): error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(29,5): error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(30,5): error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'string | number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(35,5): error TS2411: Property 'foo2' of type 'string' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(37,5): error TS2411: Property 'foo4' of type 'boolean' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(39,5): error TS2411: Property 'foo6' of type 'Date' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(40,5): error TS2411: Property 'foo7' of type 'RegExp' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(41,5): error TS2411: Property 'foo8' of type '{ bar: number; }' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(42,5): error TS2411: Property 'foo9' of type 'I8' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(43,5): error TS2411: Property 'foo10' of type 'A' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(44,5): error TS2411: Property 'foo11' of type 'A2' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(45,5): error TS2411: Property 'foo12' of type '(x: any) => number' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(46,5): error TS2411: Property 'foo13' of type '(x: T) => T' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(47,5): error TS2411: Property 'foo14' of type 'typeof f' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(48,5): error TS2411: Property 'foo15' of type 'typeof c' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(49,5): error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(50,5): error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(51,5): error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'number | E'. + + +==== tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts (29 errors) ==== + enum E { e1, e2 } + interface I8 { [x: string]: number[]; } + class A { foo: number; } + class A2 { foo: T; } + function f() { } + module f { export var bar = 1; } + class c { baz: string } + module c { export var bar = 1; } + + // A type T is a subtype of a union type U if T is a subtype of any type in U. + interface I1 { + [x: string]: string | number; + foo: any; // ok + foo2: string; // ok + foo3: number; // ok + foo4: boolean; // error + ~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo4' of type 'boolean' is not assignable to string index type 'string | number'. + foo5: E; // ok - subtype of number + foo6: Date; // error + ~~~~~~~~~~~ +!!! error TS2411: Property 'foo6' of type 'Date' is not assignable to string index type 'string | number'. + foo7: RegExp; // error + ~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo7' of type 'RegExp' is not assignable to string index type 'string | number'. + foo8: { bar: number }; // error + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo8' of type '{ bar: number; }' is not assignable to string index type 'string | number'. + foo9: I8; // error + ~~~~~~~~~ +!!! error TS2411: Property 'foo9' of type 'I8' is not assignable to string index type 'string | number'. + foo10: A; // error + ~~~~~~~~~ +!!! error TS2411: Property 'foo10' of type 'A' is not assignable to string index type 'string | number'. + foo11: A2; // error + ~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo11' of type 'A2' is not assignable to string index type 'string | number'. + foo12: (x) => number; //error + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo12' of type '(x: any) => number' is not assignable to string index type 'string | number'. + foo13: (x: T) => T; // error + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo13' of type '(x: T) => T' is not assignable to string index type 'string | number'. + foo14: typeof f; // error + ~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo14' of type 'typeof f' is not assignable to string index type 'string | number'. + foo15: typeof c; // error + ~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo15' of type 'typeof c' is not assignable to string index type 'string | number'. + foo16: T; // error + ~~~~~~~~~ +!!! error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'string | number'. + foo17: Object; // error + ~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'string | number'. + foo18: {}; // error + ~~~~~~~~~~ +!!! error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'string | number'. + } + interface I2 { + [x: string]: E | number; + foo: any; // ok + foo2: string; // error + ~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo2' of type 'string' is not assignable to string index type 'number | E'. + foo3: number; // ok + foo4: boolean; // error + ~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo4' of type 'boolean' is not assignable to string index type 'number | E'. + foo5: E; // ok + foo6: Date; // error + ~~~~~~~~~~~ +!!! error TS2411: Property 'foo6' of type 'Date' is not assignable to string index type 'number | E'. + foo7: RegExp; // error + ~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo7' of type 'RegExp' is not assignable to string index type 'number | E'. + foo8: { bar: number }; // error + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo8' of type '{ bar: number; }' is not assignable to string index type 'number | E'. + foo9: I8; // error + ~~~~~~~~~ +!!! error TS2411: Property 'foo9' of type 'I8' is not assignable to string index type 'number | E'. + foo10: A; // error + ~~~~~~~~~ +!!! error TS2411: Property 'foo10' of type 'A' is not assignable to string index type 'number | E'. + foo11: A2; // error + ~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo11' of type 'A2' is not assignable to string index type 'number | E'. + foo12: (x) => number; //error + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo12' of type '(x: any) => number' is not assignable to string index type 'number | E'. + foo13: (x: T) => T; // error + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo13' of type '(x: T) => T' is not assignable to string index type 'number | E'. + foo14: typeof f; // error + ~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo14' of type 'typeof f' is not assignable to string index type 'number | E'. + foo15: typeof c; // error + ~~~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo15' of type 'typeof c' is not assignable to string index type 'number | E'. + foo16: T; // error + ~~~~~~~~~ +!!! error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'number | E'. + foo17: Object; // error + ~~~~~~~~~~~~~~ +!!! error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'number | E'. + foo18: {}; // error + ~~~~~~~~~~ +!!! error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'number | E'. + } \ No newline at end of file diff --git a/tests/baselines/reference/subtypesOfUnion.js b/tests/baselines/reference/subtypesOfUnion.js new file mode 100644 index 00000000000..a18ebb944b9 --- /dev/null +++ b/tests/baselines/reference/subtypesOfUnion.js @@ -0,0 +1,85 @@ +//// [subtypesOfUnion.ts] +enum E { e1, e2 } +interface I8 { [x: string]: number[]; } +class A { foo: number; } +class A2 { foo: T; } +function f() { } +module f { export var bar = 1; } +class c { baz: string } +module c { export var bar = 1; } + +// A type T is a subtype of a union type U if T is a subtype of any type in U. +interface I1 { + [x: string]: string | number; + foo: any; // ok + foo2: string; // ok + foo3: number; // ok + foo4: boolean; // error + foo5: E; // ok - subtype of number + foo6: Date; // error + foo7: RegExp; // error + foo8: { bar: number }; // error + foo9: I8; // error + foo10: A; // error + foo11: A2; // error + foo12: (x) => number; //error + foo13: (x: T) => T; // error + foo14: typeof f; // error + foo15: typeof c; // error + foo16: T; // error + foo17: Object; // error + foo18: {}; // error +} +interface I2 { + [x: string]: E | number; + foo: any; // ok + foo2: string; // error + foo3: number; // ok + foo4: boolean; // error + foo5: E; // ok + foo6: Date; // error + foo7: RegExp; // error + foo8: { bar: number }; // error + foo9: I8; // error + foo10: A; // error + foo11: A2; // error + foo12: (x) => number; //error + foo13: (x: T) => T; // error + foo14: typeof f; // error + foo15: typeof c; // error + foo16: T; // error + foo17: Object; // error + foo18: {}; // error +} + +//// [subtypesOfUnion.js] +var E; +(function (E) { + E[E["e1"] = 0] = "e1"; + E[E["e2"] = 1] = "e2"; +})(E || (E = {})); +var A = (function () { + function A() { + } + return A; +})(); +var A2 = (function () { + function A2() { + } + return A2; +})(); +function f() { +} +var f; +(function (f) { + f.bar = 1; +})(f || (f = {})); +var c = (function () { + function c() { + } + return c; +})(); +var c; +(function (c) { + c.bar = 1; +})(c || (c = {})); diff --git a/tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts b/tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts new file mode 100644 index 00000000000..c20bafeeabf --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts @@ -0,0 +1,52 @@ +enum E { e1, e2 } +interface I8 { [x: string]: number[]; } +class A { foo: number; } +class A2 { foo: T; } +function f() { } +module f { export var bar = 1; } +class c { baz: string } +module c { export var bar = 1; } + +// A type T is a subtype of a union type U if T is a subtype of any type in U. +interface I1 { + [x: string]: string | number; + foo: any; // ok + foo2: string; // ok + foo3: number; // ok + foo4: boolean; // error + foo5: E; // ok - subtype of number + foo6: Date; // error + foo7: RegExp; // error + foo8: { bar: number }; // error + foo9: I8; // error + foo10: A; // error + foo11: A2; // error + foo12: (x) => number; //error + foo13: (x: T) => T; // error + foo14: typeof f; // error + foo15: typeof c; // error + foo16: T; // error + foo17: Object; // error + foo18: {}; // error +} +interface I2 { + [x: string]: E | number; + foo: any; // ok + foo2: string; // error + foo3: number; // ok + foo4: boolean; // error + foo5: E; // ok + foo6: Date; // error + foo7: RegExp; // error + foo8: { bar: number }; // error + foo9: I8; // error + foo10: A; // error + foo11: A2; // error + foo12: (x) => number; //error + foo13: (x: T) => T; // error + foo14: typeof f; // error + foo15: typeof c; // error + foo16: T; // error + foo17: Object; // error + foo18: {}; // error +} \ No newline at end of file From 1f3653b32e98e1fe5861c3c3aa16881aaa60a16e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 10:08:40 -0800 Subject: [PATCH 05/41] =?UTF-8?q?Tests=20for=20assignment=20compatibility?= =?UTF-8?q?=20of=20union=20types=20=E2=80=A2=09A=20union=20type=20U=20is?= =?UTF-8?q?=20assignable=20to=20a=20type=20T=20if=20each=20type=20in=20U?= =?UTF-8?q?=20is=20assignable=20to=20T.=20=E2=80=A2=09A=20type=20T=20is=20?= =?UTF-8?q?assignable=20to=20a=20union=20type=20U=20if=20T=20is=20assignab?= =?UTF-8?q?le=20to=20any=20type=20in=20U.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unionTypesAssignability.errors.txt | 154 ++++++++++++++++ .../reference/unionTypesAssignability.js | 165 ++++++++++++++++++ .../unionTypesAssignability.ts | 71 ++++++++ 3 files changed, 390 insertions(+) create mode 100644 tests/baselines/reference/unionTypesAssignability.errors.txt create mode 100644 tests/baselines/reference/unionTypesAssignability.js create mode 100644 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts diff --git a/tests/baselines/reference/unionTypesAssignability.errors.txt b/tests/baselines/reference/unionTypesAssignability.errors.txt new file mode 100644 index 00000000000..b32f71a38c1 --- /dev/null +++ b/tests/baselines/reference/unionTypesAssignability.errors.txt @@ -0,0 +1,154 @@ +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(18,1): error TS2323: Type 'E' is not assignable to type 'D'. + Property 'foo1' is missing in type 'E'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(19,1): error TS2323: Type 'D | E' is not assignable to type 'D'. + Type 'E' is not assignable to type 'D'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(20,1): error TS2323: Type 'D' is not assignable to type 'E'. + Property 'foo2' is missing in type 'D'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(22,1): error TS2323: Type 'D | E' is not assignable to type 'E'. + Type 'D' is not assignable to type 'E'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(24,1): error TS2323: Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(25,1): error TS2323: Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(26,1): error TS2323: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(28,1): error TS2323: Type 'string | number' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(31,1): error TS2323: Type 'C' is not assignable to type 'D'. + Property 'foo1' is missing in type 'C'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(32,1): error TS2323: Type 'C' is not assignable to type 'E'. + Property 'foo2' is missing in type 'C'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(33,1): error TS2323: Type 'C' is not assignable to type 'D | E'. + Type 'C' is not assignable to type 'E'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(35,1): error TS2323: Type 'D' is not assignable to type 'E'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(37,1): error TS2323: Type 'E' is not assignable to type 'D'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(41,1): error TS2323: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(43,1): error TS2323: Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(64,5): error TS2323: Type 'U' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(65,5): error TS2323: Type 'T' is not assignable to type 'U'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(69,5): error TS2323: Type 'T | U' is not assignable to type 'T'. + Type 'U' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(70,5): error TS2323: Type 'T | U' is not assignable to type 'U'. + Type 'T' is not assignable to type 'U'. + + +==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts (19 errors) ==== + var unionNumberString: number | string; + class C { } + class D extends C { foo1() { } } + class E extends C { foo2() { } } + var unionDE: D | E; + + var num: number; + var str: string; + var c: C; + var d: D; + var e: E; + + // A union type U is assignable to a type T if each type in U is assignable to T + c = d; + c = e; + c = unionDE; // ok + d = d; + d = e; + ~ +!!! error TS2323: Type 'E' is not assignable to type 'D'. +!!! error TS2323: Property 'foo1' is missing in type 'E'. + d = unionDE; // error e is not assignable to d + ~ +!!! error TS2323: Type 'D | E' is not assignable to type 'D'. +!!! error TS2323: Type 'E' is not assignable to type 'D'. + e = d; + ~ +!!! error TS2323: Type 'D' is not assignable to type 'E'. +!!! error TS2323: Property 'foo2' is missing in type 'D'. + e = e; + e = unionDE; // error d is not assignable to e + ~ +!!! error TS2323: Type 'D | E' is not assignable to type 'E'. +!!! error TS2323: Type 'D' is not assignable to type 'E'. + num = num; + num = str; + ~~~ +!!! error TS2323: Type 'string' is not assignable to type 'number'. + num = unionNumberString; // error string is not assignable to number + ~~~ +!!! error TS2323: Type 'string | number' is not assignable to type 'number'. +!!! error TS2323: Type 'string' is not assignable to type 'number'. + str = num; + ~~~ +!!! error TS2323: Type 'number' is not assignable to type 'string'. + str = str; + str = unionNumberString; // error since number is not assignable to string + ~~~ +!!! error TS2323: Type 'string | number' is not assignable to type 'string'. +!!! error TS2323: Type 'number' is not assignable to type 'string'. + + // A type T is assignable to a union type U if T is assignable to any type in U + d = c; + ~ +!!! error TS2323: Type 'C' is not assignable to type 'D'. +!!! error TS2323: Property 'foo1' is missing in type 'C'. + e = c; + ~ +!!! error TS2323: Type 'C' is not assignable to type 'E'. +!!! error TS2323: Property 'foo2' is missing in type 'C'. + unionDE = c; // error since C is not assinable to either D or E + ~~~~~~~ +!!! error TS2323: Type 'C' is not assignable to type 'D | E'. +!!! error TS2323: Type 'C' is not assignable to type 'E'. + d = d; + e = d; + ~ +!!! error TS2323: Type 'D' is not assignable to type 'E'. + unionDE = d; // ok + d = e; + ~ +!!! error TS2323: Type 'E' is not assignable to type 'D'. + e = e; + unionDE = e; // ok + num = num; + str = num; + ~~~ +!!! error TS2323: Type 'number' is not assignable to type 'string'. + unionNumberString = num; // ok + num = str; + ~~~ +!!! error TS2323: Type 'string' is not assignable to type 'number'. + str = str; + unionNumberString = str; // ok + + // Any + var anyVar: any; + anyVar = unionDE; + anyVar = unionNumberString; + unionDE = anyVar; + unionNumberString = anyVar; + + // null + unionDE = null; + unionNumberString = null; + + // undefined + unionDE = undefined; + unionNumberString = undefined; + + // type parameters + function foo(t: T, u: U) { + t = u; // error + ~ +!!! error TS2323: Type 'U' is not assignable to type 'T'. + u = t; // error + ~ +!!! error TS2323: Type 'T' is not assignable to type 'U'. + var x : T | U; + x = t; // ok + x = u; // ok + t = x; // error U not assignable to T + ~ +!!! error TS2323: Type 'T | U' is not assignable to type 'T'. +!!! error TS2323: Type 'U' is not assignable to type 'T'. + u = x; // error T not assignable to U + ~ +!!! error TS2323: Type 'T | U' is not assignable to type 'U'. +!!! error TS2323: Type 'T' is not assignable to type 'U'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/unionTypesAssignability.js b/tests/baselines/reference/unionTypesAssignability.js new file mode 100644 index 00000000000..a67f23bb09f --- /dev/null +++ b/tests/baselines/reference/unionTypesAssignability.js @@ -0,0 +1,165 @@ +//// [unionTypesAssignability.ts] +var unionNumberString: number | string; +class C { } +class D extends C { foo1() { } } +class E extends C { foo2() { } } +var unionDE: D | E; + +var num: number; +var str: string; +var c: C; +var d: D; +var e: E; + +// A union type U is assignable to a type T if each type in U is assignable to T +c = d; +c = e; +c = unionDE; // ok +d = d; +d = e; +d = unionDE; // error e is not assignable to d +e = d; +e = e; +e = unionDE; // error d is not assignable to e +num = num; +num = str; +num = unionNumberString; // error string is not assignable to number +str = num; +str = str; +str = unionNumberString; // error since number is not assignable to string + +// A type T is assignable to a union type U if T is assignable to any type in U +d = c; +e = c; +unionDE = c; // error since C is not assinable to either D or E +d = d; +e = d; +unionDE = d; // ok +d = e; +e = e; +unionDE = e; // ok +num = num; +str = num; +unionNumberString = num; // ok +num = str; +str = str; +unionNumberString = str; // ok + +// Any +var anyVar: any; +anyVar = unionDE; +anyVar = unionNumberString; +unionDE = anyVar; +unionNumberString = anyVar; + +// null +unionDE = null; +unionNumberString = null; + +// undefined +unionDE = undefined; +unionNumberString = undefined; + +// type parameters +function foo(t: T, u: U) { + t = u; // error + u = t; // error + var x : T | U; + x = t; // ok + x = u; // ok + t = x; // error U not assignable to T + u = x; // error T not assignable to U +} + + +//// [unionTypesAssignability.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var unionNumberString; +var C = (function () { + function C() { + } + return C; +})(); +var D = (function (_super) { + __extends(D, _super); + function D() { + _super.apply(this, arguments); + } + D.prototype.foo1 = function () { + }; + return D; +})(C); +var E = (function (_super) { + __extends(E, _super); + function E() { + _super.apply(this, arguments); + } + E.prototype.foo2 = function () { + }; + return E; +})(C); +var unionDE; +var num; +var str; +var c; +var d; +var e; +// A union type U is assignable to a type T if each type in U is assignable to T +c = d; +c = e; +c = unionDE; // ok +d = d; +d = e; +d = unionDE; // error e is not assignable to d +e = d; +e = e; +e = unionDE; // error d is not assignable to e +num = num; +num = str; +num = unionNumberString; // error string is not assignable to number +str = num; +str = str; +str = unionNumberString; // error since number is not assignable to string +// A type T is assignable to a union type U if T is assignable to any type in U +d = c; +e = c; +unionDE = c; // error since C is not assinable to either D or E +d = d; +e = d; +unionDE = d; // ok +d = e; +e = e; +unionDE = e; // ok +num = num; +str = num; +unionNumberString = num; // ok +num = str; +str = str; +unionNumberString = str; // ok +// Any +var anyVar; +anyVar = unionDE; +anyVar = unionNumberString; +unionDE = anyVar; +unionNumberString = anyVar; +// null +unionDE = null; +unionNumberString = null; +// undefined +unionDE = undefined; +unionNumberString = undefined; +// type parameters +function foo(t, u) { + t = u; // error + u = t; // error + var x; + x = t; // ok + x = u; // ok + t = x; // error U not assignable to T + u = x; // error T not assignable to U +} diff --git a/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts b/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts new file mode 100644 index 00000000000..9ceee8845a5 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts @@ -0,0 +1,71 @@ +var unionNumberString: number | string; +class C { } +class D extends C { foo1() { } } +class E extends C { foo2() { } } +var unionDE: D | E; + +var num: number; +var str: string; +var c: C; +var d: D; +var e: E; + +// A union type U is assignable to a type T if each type in U is assignable to T +c = d; +c = e; +c = unionDE; // ok +d = d; +d = e; +d = unionDE; // error e is not assignable to d +e = d; +e = e; +e = unionDE; // error d is not assignable to e +num = num; +num = str; +num = unionNumberString; // error string is not assignable to number +str = num; +str = str; +str = unionNumberString; // error since number is not assignable to string + +// A type T is assignable to a union type U if T is assignable to any type in U +d = c; +e = c; +unionDE = c; // error since C is not assinable to either D or E +d = d; +e = d; +unionDE = d; // ok +d = e; +e = e; +unionDE = e; // ok +num = num; +str = num; +unionNumberString = num; // ok +num = str; +str = str; +unionNumberString = str; // ok + +// Any +var anyVar: any; +anyVar = unionDE; +anyVar = unionNumberString; +unionDE = anyVar; +unionNumberString = anyVar; + +// null +unionDE = null; +unionNumberString = null; + +// undefined +unionDE = undefined; +unionNumberString = undefined; + +// type parameters +function foo(t: T, u: U) { + t = u; // error + u = t; // error + var x : T | U; + x = t; // ok + x = u; // ok + t = x; // error U not assignable to T + u = x; // error T not assignable to U +} From 357bd87612ba2e1f5302562a922f943405ea70b3 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 13:20:30 -0800 Subject: [PATCH 06/41] Tests for union members: If each type in U has a property P, U has a property P of a union type of the types of P from each type in U. --- .../reference/unionTypeEquivalence.js | 4 +- .../reference/unionTypeEquivalence.types | 3 +- .../reference/unionTypeMembers.errors.txt | 72 +++++++++++++++++ tests/baselines/reference/unionTypeMembers.js | 79 +++++++++++++++++++ .../types/union/unionTypeEquivalence.ts | 2 +- .../types/union/unionTypeMembers.ts | 54 +++++++++++++ 6 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/unionTypeMembers.errors.txt create mode 100644 tests/baselines/reference/unionTypeMembers.js create mode 100644 tests/cases/conformance/types/union/unionTypeMembers.ts diff --git a/tests/baselines/reference/unionTypeEquivalence.js b/tests/baselines/reference/unionTypeEquivalence.js index 3698ecd2f92..f9fdf2e58d7 100644 --- a/tests/baselines/reference/unionTypeEquivalence.js +++ b/tests/baselines/reference/unionTypeEquivalence.js @@ -1,7 +1,7 @@ //// [unionTypeEquivalence.ts] // A | B is equivalent to A if B is a subtype of A class C { } -class D extends C { } +class D extends C { foo() { } } var x: C; var x : C | D; @@ -37,6 +37,8 @@ var D = (function (_super) { function D() { _super.apply(this, arguments); } + D.prototype.foo = function () { + }; return D; })(C); var x; diff --git a/tests/baselines/reference/unionTypeEquivalence.types b/tests/baselines/reference/unionTypeEquivalence.types index 53e95659120..c4990a58132 100644 --- a/tests/baselines/reference/unionTypeEquivalence.types +++ b/tests/baselines/reference/unionTypeEquivalence.types @@ -3,9 +3,10 @@ class C { } >C : C -class D extends C { } +class D extends C { foo() { } } >D : D >C : C +>foo : () => void var x: C; >x : C diff --git a/tests/baselines/reference/unionTypeMembers.errors.txt b/tests/baselines/reference/unionTypeMembers.errors.txt new file mode 100644 index 00000000000..21f1204ac6d --- /dev/null +++ b/tests/baselines/reference/unionTypeMembers.errors.txt @@ -0,0 +1,72 @@ +tests/cases/conformance/types/union/unionTypeMembers.ts(44,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeMembers.ts(51,3): error TS2339: Property 'propertyOnlyInI1' does not exist on type 'I1 | I2'. +tests/cases/conformance/types/union/unionTypeMembers.ts(52,3): error TS2339: Property 'propertyOnlyInI2' does not exist on type 'I1 | I2'. +tests/cases/conformance/types/union/unionTypeMembers.ts(53,3): error TS2339: Property 'methodOnlyInI1' does not exist on type 'I1 | I2'. +tests/cases/conformance/types/union/unionTypeMembers.ts(54,3): error TS2339: Property 'methodOnlyInI2' does not exist on type 'I1 | I2'. + + +==== tests/cases/conformance/types/union/unionTypeMembers.ts (5 errors) ==== + interface I1 { + commonMethodType(a: string): string; + commonPropertyType: string; + + commonMethodDifferentParameterType(a: string): string; + commonMethodDifferentReturnType(a: string): string; + commonPropertyDifferenType: string; + + commonMethodWithTypeParameter(a: T): T; + commonMethodWithOwnTypeParameter(a: U): U; + + methodOnlyInI1(a: string): string; + propertyOnlyInI1: string; + } + + interface I2 { + commonMethodType(a: string): string; + commonPropertyType: string; + + commonMethodDifferentParameterType(a: number): number; + commonMethodDifferentReturnType(a: string): number; + commonPropertyDifferenType: number; + + commonMethodWithTypeParameter(a: T): T; + commonMethodWithOwnTypeParameter(a: U): U; + + methodOnlyInI2(a: string): string; + propertyOnlyInI2: string; + } + + // a union type U has those members that are present in every one of its constituent types, + // with types that are unions of the respective members in the constituent types + var x : I1 | I2; + var str: string; + var num: number; + var strOrNum: string | number; + + // If each type in U has a property P, U has a property P of a union type of the types of P from each type in U. + str = x.commonPropertyType; // string + str = x.commonMethodType(str); // (a: string) => string so result should be string + strOrNum = x.commonPropertyDifferenType; + strOrNum = x.commonMethodDifferentReturnType(str); // string | union + x.commonMethodDifferentParameterType; // No error - property exists + x.commonMethodDifferentParameterType(strOrNum); // error - no call signatures because the type of this property is ((a: string) => string) | (a: number) => number + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + // and the call signatures arent identical + num = x.commonMethodWithTypeParameter(num); + num = x.commonMethodWithOwnTypeParameter(num); + str = x.commonMethodWithOwnTypeParameter(str); + strOrNum = x.commonMethodWithOwnTypeParameter(strOrNum); + + x.propertyOnlyInI1; // error + ~~~~~~~~~~~~~~~~ +!!! error TS2339: Property 'propertyOnlyInI1' does not exist on type 'I1 | I2'. + x.propertyOnlyInI2; // error + ~~~~~~~~~~~~~~~~ +!!! error TS2339: Property 'propertyOnlyInI2' does not exist on type 'I1 | I2'. + x.methodOnlyInI1("hello"); // error + ~~~~~~~~~~~~~~ +!!! error TS2339: Property 'methodOnlyInI1' does not exist on type 'I1 | I2'. + x.methodOnlyInI2(10); // error + ~~~~~~~~~~~~~~ +!!! error TS2339: Property 'methodOnlyInI2' does not exist on type 'I1 | I2'. \ No newline at end of file diff --git a/tests/baselines/reference/unionTypeMembers.js b/tests/baselines/reference/unionTypeMembers.js new file mode 100644 index 00000000000..b03572246b4 --- /dev/null +++ b/tests/baselines/reference/unionTypeMembers.js @@ -0,0 +1,79 @@ +//// [unionTypeMembers.ts] +interface I1 { + commonMethodType(a: string): string; + commonPropertyType: string; + + commonMethodDifferentParameterType(a: string): string; + commonMethodDifferentReturnType(a: string): string; + commonPropertyDifferenType: string; + + commonMethodWithTypeParameter(a: T): T; + commonMethodWithOwnTypeParameter(a: U): U; + + methodOnlyInI1(a: string): string; + propertyOnlyInI1: string; +} + +interface I2 { + commonMethodType(a: string): string; + commonPropertyType: string; + + commonMethodDifferentParameterType(a: number): number; + commonMethodDifferentReturnType(a: string): number; + commonPropertyDifferenType: number; + + commonMethodWithTypeParameter(a: T): T; + commonMethodWithOwnTypeParameter(a: U): U; + + methodOnlyInI2(a: string): string; + propertyOnlyInI2: string; +} + +// a union type U has those members that are present in every one of its constituent types, +// with types that are unions of the respective members in the constituent types +var x : I1 | I2; +var str: string; +var num: number; +var strOrNum: string | number; + +// If each type in U has a property P, U has a property P of a union type of the types of P from each type in U. +str = x.commonPropertyType; // string +str = x.commonMethodType(str); // (a: string) => string so result should be string +strOrNum = x.commonPropertyDifferenType; +strOrNum = x.commonMethodDifferentReturnType(str); // string | union +x.commonMethodDifferentParameterType; // No error - property exists +x.commonMethodDifferentParameterType(strOrNum); // error - no call signatures because the type of this property is ((a: string) => string) | (a: number) => number + // and the call signatures arent identical +num = x.commonMethodWithTypeParameter(num); +num = x.commonMethodWithOwnTypeParameter(num); +str = x.commonMethodWithOwnTypeParameter(str); +strOrNum = x.commonMethodWithOwnTypeParameter(strOrNum); + +x.propertyOnlyInI1; // error +x.propertyOnlyInI2; // error +x.methodOnlyInI1("hello"); // error +x.methodOnlyInI2(10); // error + +//// [unionTypeMembers.js] +// a union type U has those members that are present in every one of its constituent types, +// with types that are unions of the respective members in the constituent types +var x; +var str; +var num; +var strOrNum; +// If each type in U has a property P, U has a property P of a union type of the types of P from each type in U. +str = x.commonPropertyType; // string +str = x.commonMethodType(str); // (a: string) => string so result should be string +strOrNum = x.commonPropertyDifferenType; +strOrNum = x.commonMethodDifferentReturnType(str); // string | union +x.commonMethodDifferentParameterType; // No error - property exists +x.commonMethodDifferentParameterType(strOrNum); // error - no call signatures because the type of this property is ((a: string) => string) | (a: number) => number +// and the call signatures arent identical +num = x.commonMethodWithTypeParameter(num); +num = x.commonMethodWithOwnTypeParameter(num); +str = x.commonMethodWithOwnTypeParameter(str); +strOrNum = x.commonMethodWithOwnTypeParameter(strOrNum); +x.propertyOnlyInI1; // error +x.propertyOnlyInI2; // error +x.methodOnlyInI1("hello"); // error +x.methodOnlyInI2(10); // error diff --git a/tests/cases/conformance/types/union/unionTypeEquivalence.ts b/tests/cases/conformance/types/union/unionTypeEquivalence.ts index 0905fde17f8..71fd6d91b65 100644 --- a/tests/cases/conformance/types/union/unionTypeEquivalence.ts +++ b/tests/cases/conformance/types/union/unionTypeEquivalence.ts @@ -1,6 +1,6 @@ // A | B is equivalent to A if B is a subtype of A class C { } -class D extends C { } +class D extends C { foo() { } } var x: C; var x : C | D; diff --git a/tests/cases/conformance/types/union/unionTypeMembers.ts b/tests/cases/conformance/types/union/unionTypeMembers.ts new file mode 100644 index 00000000000..73c6867e9ac --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeMembers.ts @@ -0,0 +1,54 @@ +interface I1 { + commonMethodType(a: string): string; + commonPropertyType: string; + + commonMethodDifferentParameterType(a: string): string; + commonMethodDifferentReturnType(a: string): string; + commonPropertyDifferenType: string; + + commonMethodWithTypeParameter(a: T): T; + commonMethodWithOwnTypeParameter(a: U): U; + + methodOnlyInI1(a: string): string; + propertyOnlyInI1: string; +} + +interface I2 { + commonMethodType(a: string): string; + commonPropertyType: string; + + commonMethodDifferentParameterType(a: number): number; + commonMethodDifferentReturnType(a: string): number; + commonPropertyDifferenType: number; + + commonMethodWithTypeParameter(a: T): T; + commonMethodWithOwnTypeParameter(a: U): U; + + methodOnlyInI2(a: string): string; + propertyOnlyInI2: string; +} + +// a union type U has those members that are present in every one of its constituent types, +// with types that are unions of the respective members in the constituent types +var x : I1 | I2; +var str: string; +var num: number; +var strOrNum: string | number; + +// If each type in U has a property P, U has a property P of a union type of the types of P from each type in U. +str = x.commonPropertyType; // string +str = x.commonMethodType(str); // (a: string) => string so result should be string +strOrNum = x.commonPropertyDifferenType; +strOrNum = x.commonMethodDifferentReturnType(str); // string | union +x.commonMethodDifferentParameterType; // No error - property exists +x.commonMethodDifferentParameterType(strOrNum); // error - no call signatures because the type of this property is ((a: string) => string) | (a: number) => number + // and the call signatures arent identical +num = x.commonMethodWithTypeParameter(num); +num = x.commonMethodWithOwnTypeParameter(num); +str = x.commonMethodWithOwnTypeParameter(str); +strOrNum = x.commonMethodWithOwnTypeParameter(strOrNum); + +x.propertyOnlyInI1; // error +x.propertyOnlyInI2; // error +x.methodOnlyInI1("hello"); // error +x.methodOnlyInI2(10); // error \ No newline at end of file From 2b8342bd79352b05403e769cb79da15d9444e7b1 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 13:20:55 -0800 Subject: [PATCH 07/41] Tests for union of call signatures If each type in U has call signatures and the sets of call signatures are identical ignoring return types, U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in U. --- .../unionTypeCallSignatures.errors.txt | 178 ++++++++++++++++++ .../reference/unionTypeCallSignatures.js | 132 +++++++++++++ .../types/union/unionTypeCallSignatures.ts | 70 +++++++ 3 files changed, 380 insertions(+) create mode 100644 tests/baselines/reference/unionTypeCallSignatures.errors.txt create mode 100644 tests/baselines/reference/unionTypeCallSignatures.js create mode 100644 tests/cases/conformance/types/union/unionTypeCallSignatures.ts diff --git a/tests/baselines/reference/unionTypeCallSignatures.errors.txt b/tests/baselines/reference/unionTypeCallSignatures.errors.txt new file mode 100644 index 00000000000..313cd477187 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures.errors.txt @@ -0,0 +1,178 @@ +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(9,43): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(10,29): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(15,29): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(16,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(19,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(20,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(21,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(24,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(25,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(26,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(29,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(30,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(31,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(36,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(37,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(40,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(41,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(42,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(43,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(46,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(47,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(48,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(49,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(55,45): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(56,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(59,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(60,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(61,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(62,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(63,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(66,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(67,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(68,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(69,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. + + +==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (35 errors) ==== + var numOrDate: number | Date; + var strOrBoolean: string | boolean; + var strOrNum: string | number; + + // If each type in U has call signatures and the sets of call signatures are identical ignoring return types, + // U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in U. + var unionOfDifferentReturnType: { (a: number): number; } | { (a: number): Date; }; + numOrDate = unionOfDifferentReturnType(10); + strOrBoolean = unionOfDifferentReturnType("hello"); // error + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + unionOfDifferentReturnType1(true); // error in type of parameter + ~~~~ +!!! error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'. + + var unionOfDifferentReturnType1: { (a: number): number; (a: string): string; } | { (a: number): Date; (a: string): boolean; }; + numOrDate = unionOfDifferentReturnType1(10); + strOrBoolean = unionOfDifferentReturnType1("hello"); + unionOfDifferentReturnType1(true); // error in type of parameter + ~~~~ +!!! error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'. + unionOfDifferentReturnType1(); // error missing parameter + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + var unionOfDifferentParameterTypes: { (a: number): number; } | { (a: string): Date; }; + unionOfDifferentParameterTypes(10);// error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + unionOfDifferentParameterTypes("hello");// error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + unionOfDifferentParameterTypes();// error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + + var unionOfDifferentNumberOfSignatures: { (a: number): number; } | { (a: number): Date; (a: string): boolean; }; + unionOfDifferentNumberOfSignatures(); // error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + unionOfDifferentNumberOfSignatures(10); // error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + + var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; + unionWithDifferentParameterCount();// no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + unionWithDifferentParameterCount("hello");// no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + unionWithDifferentParameterCount("hello", 10);// no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + + var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; + strOrNum = unionWithOptionalParameter1('hello'); + strOrNum = unionWithOptionalParameter1('hello', 10); + strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + strOrNum = unionWithOptionalParameter1(); // error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + var unionWithOptionalParameter2: { (a: string, b?: number): string; } | { (a: string, b: number): number }; + strOrNum = unionWithOptionalParameter2('hello'); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithOptionalParameter2('hello', 10); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithOptionalParameter2(); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + + var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; + strOrNum = unionWithOptionalParameter3('hello'); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithOptionalParameter3(); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + + var unionWithRestParameter1: { (a: string, ...b: number[]): string; } | { (a: string, ...b: number[]): number }; + strOrNum = unionWithRestParameter1('hello'); + strOrNum = unionWithRestParameter1('hello', 10); + strOrNum = unionWithRestParameter1('hello', 10, 11); + strOrNum = unionWithRestParameter1('hello', "hello"); // error in parameter type + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + strOrNum = unionWithRestParameter1(); // error + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + var unionWithRestParameter2: { (a: string, ...b: number[]): string; } | { (a: string, b: number): number }; + strOrNum = unionWithRestParameter2('hello'); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter2('hello', 10); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter2('hello', 10, 11); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter2(); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + + var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; + strOrNum = unionWithRestParameter3('hello'); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter3('hello', 10); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter3(); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. \ No newline at end of file diff --git a/tests/baselines/reference/unionTypeCallSignatures.js b/tests/baselines/reference/unionTypeCallSignatures.js new file mode 100644 index 00000000000..a4000038ce6 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures.js @@ -0,0 +1,132 @@ +//// [unionTypeCallSignatures.ts] +var numOrDate: number | Date; +var strOrBoolean: string | boolean; +var strOrNum: string | number; + +// If each type in U has call signatures and the sets of call signatures are identical ignoring return types, +// U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in U. +var unionOfDifferentReturnType: { (a: number): number; } | { (a: number): Date; }; +numOrDate = unionOfDifferentReturnType(10); +strOrBoolean = unionOfDifferentReturnType("hello"); // error +unionOfDifferentReturnType1(true); // error in type of parameter + +var unionOfDifferentReturnType1: { (a: number): number; (a: string): string; } | { (a: number): Date; (a: string): boolean; }; +numOrDate = unionOfDifferentReturnType1(10); +strOrBoolean = unionOfDifferentReturnType1("hello"); +unionOfDifferentReturnType1(true); // error in type of parameter +unionOfDifferentReturnType1(); // error missing parameter + +var unionOfDifferentParameterTypes: { (a: number): number; } | { (a: string): Date; }; +unionOfDifferentParameterTypes(10);// error - no call signatures +unionOfDifferentParameterTypes("hello");// error - no call signatures +unionOfDifferentParameterTypes();// error - no call signatures + +var unionOfDifferentNumberOfSignatures: { (a: number): number; } | { (a: number): Date; (a: string): boolean; }; +unionOfDifferentNumberOfSignatures(); // error - no call signatures +unionOfDifferentNumberOfSignatures(10); // error - no call signatures +unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures + + var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; +unionWithDifferentParameterCount();// no call signature +unionWithDifferentParameterCount("hello");// no call signature +unionWithDifferentParameterCount("hello", 10);// no call signature + + var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; +strOrNum = unionWithOptionalParameter1('hello'); +strOrNum = unionWithOptionalParameter1('hello', 10); +strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type +strOrNum = unionWithOptionalParameter1(); // error + +var unionWithOptionalParameter2: { (a: string, b?: number): string; } | { (a: string, b: number): number }; +strOrNum = unionWithOptionalParameter2('hello'); // error no call signature +strOrNum = unionWithOptionalParameter2('hello', 10); // error no call signature +strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signature +strOrNum = unionWithOptionalParameter2(); // error no call signature + +var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; +strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature +strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature +strOrNum = unionWithOptionalParameter3(); // error no call signature + +var unionWithRestParameter1: { (a: string, ...b: number[]): string; } | { (a: string, ...b: number[]): number }; +strOrNum = unionWithRestParameter1('hello'); +strOrNum = unionWithRestParameter1('hello', 10); +strOrNum = unionWithRestParameter1('hello', 10, 11); +strOrNum = unionWithRestParameter1('hello', "hello"); // error in parameter type +strOrNum = unionWithRestParameter1(); // error + +var unionWithRestParameter2: { (a: string, ...b: number[]): string; } | { (a: string, b: number): number }; +strOrNum = unionWithRestParameter2('hello'); // error no call signature +strOrNum = unionWithRestParameter2('hello', 10); // error no call signature +strOrNum = unionWithRestParameter2('hello', 10, 11); // error no call signature +strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature +strOrNum = unionWithRestParameter2(); // error no call signature + +var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; +strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello', 10); // error no call signature +strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature +strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature +strOrNum = unionWithRestParameter3(); // error no call signature + +//// [unionTypeCallSignatures.js] +var numOrDate; +var strOrBoolean; +var strOrNum; +// If each type in U has call signatures and the sets of call signatures are identical ignoring return types, +// U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in U. +var unionOfDifferentReturnType; +numOrDate = unionOfDifferentReturnType(10); +strOrBoolean = unionOfDifferentReturnType("hello"); // error +unionOfDifferentReturnType1(true); // error in type of parameter +var unionOfDifferentReturnType1; +numOrDate = unionOfDifferentReturnType1(10); +strOrBoolean = unionOfDifferentReturnType1("hello"); +unionOfDifferentReturnType1(true); // error in type of parameter +unionOfDifferentReturnType1(); // error missing parameter +var unionOfDifferentParameterTypes; +unionOfDifferentParameterTypes(10); // error - no call signatures +unionOfDifferentParameterTypes("hello"); // error - no call signatures +unionOfDifferentParameterTypes(); // error - no call signatures +var unionOfDifferentNumberOfSignatures; +unionOfDifferentNumberOfSignatures(); // error - no call signatures +unionOfDifferentNumberOfSignatures(10); // error - no call signatures +unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures +var unionWithDifferentParameterCount; +unionWithDifferentParameterCount(); // no call signature +unionWithDifferentParameterCount("hello"); // no call signature +unionWithDifferentParameterCount("hello", 10); // no call signature +var unionWithOptionalParameter1; +strOrNum = unionWithOptionalParameter1('hello'); +strOrNum = unionWithOptionalParameter1('hello', 10); +strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type +strOrNum = unionWithOptionalParameter1(); // error +var unionWithOptionalParameter2; +strOrNum = unionWithOptionalParameter2('hello'); // error no call signature +strOrNum = unionWithOptionalParameter2('hello', 10); // error no call signature +strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signature +strOrNum = unionWithOptionalParameter2(); // error no call signature +var unionWithOptionalParameter3; +strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature +strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature +strOrNum = unionWithOptionalParameter3(); // error no call signature +var unionWithRestParameter1; +strOrNum = unionWithRestParameter1('hello'); +strOrNum = unionWithRestParameter1('hello', 10); +strOrNum = unionWithRestParameter1('hello', 10, 11); +strOrNum = unionWithRestParameter1('hello', "hello"); // error in parameter type +strOrNum = unionWithRestParameter1(); // error +var unionWithRestParameter2; +strOrNum = unionWithRestParameter2('hello'); // error no call signature +strOrNum = unionWithRestParameter2('hello', 10); // error no call signature +strOrNum = unionWithRestParameter2('hello', 10, 11); // error no call signature +strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature +strOrNum = unionWithRestParameter2(); // error no call signature +var unionWithRestParameter3; +strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello', 10); // error no call signature +strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature +strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature +strOrNum = unionWithRestParameter3(); // error no call signature diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures.ts new file mode 100644 index 00000000000..1261de3299e --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures.ts @@ -0,0 +1,70 @@ +var numOrDate: number | Date; +var strOrBoolean: string | boolean; +var strOrNum: string | number; + +// If each type in U has call signatures and the sets of call signatures are identical ignoring return types, +// U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in U. +var unionOfDifferentReturnType: { (a: number): number; } | { (a: number): Date; }; +numOrDate = unionOfDifferentReturnType(10); +strOrBoolean = unionOfDifferentReturnType("hello"); // error +unionOfDifferentReturnType1(true); // error in type of parameter + +var unionOfDifferentReturnType1: { (a: number): number; (a: string): string; } | { (a: number): Date; (a: string): boolean; }; +numOrDate = unionOfDifferentReturnType1(10); +strOrBoolean = unionOfDifferentReturnType1("hello"); +unionOfDifferentReturnType1(true); // error in type of parameter +unionOfDifferentReturnType1(); // error missing parameter + +var unionOfDifferentParameterTypes: { (a: number): number; } | { (a: string): Date; }; +unionOfDifferentParameterTypes(10);// error - no call signatures +unionOfDifferentParameterTypes("hello");// error - no call signatures +unionOfDifferentParameterTypes();// error - no call signatures + +var unionOfDifferentNumberOfSignatures: { (a: number): number; } | { (a: number): Date; (a: string): boolean; }; +unionOfDifferentNumberOfSignatures(); // error - no call signatures +unionOfDifferentNumberOfSignatures(10); // error - no call signatures +unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures + + var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; +unionWithDifferentParameterCount();// no call signature +unionWithDifferentParameterCount("hello");// no call signature +unionWithDifferentParameterCount("hello", 10);// no call signature + + var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; +strOrNum = unionWithOptionalParameter1('hello'); +strOrNum = unionWithOptionalParameter1('hello', 10); +strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type +strOrNum = unionWithOptionalParameter1(); // error + +var unionWithOptionalParameter2: { (a: string, b?: number): string; } | { (a: string, b: number): number }; +strOrNum = unionWithOptionalParameter2('hello'); // error no call signature +strOrNum = unionWithOptionalParameter2('hello', 10); // error no call signature +strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signature +strOrNum = unionWithOptionalParameter2(); // error no call signature + +var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; +strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature +strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature +strOrNum = unionWithOptionalParameter3(); // error no call signature + +var unionWithRestParameter1: { (a: string, ...b: number[]): string; } | { (a: string, ...b: number[]): number }; +strOrNum = unionWithRestParameter1('hello'); +strOrNum = unionWithRestParameter1('hello', 10); +strOrNum = unionWithRestParameter1('hello', 10, 11); +strOrNum = unionWithRestParameter1('hello', "hello"); // error in parameter type +strOrNum = unionWithRestParameter1(); // error + +var unionWithRestParameter2: { (a: string, ...b: number[]): string; } | { (a: string, b: number): number }; +strOrNum = unionWithRestParameter2('hello'); // error no call signature +strOrNum = unionWithRestParameter2('hello', 10); // error no call signature +strOrNum = unionWithRestParameter2('hello', 10, 11); // error no call signature +strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature +strOrNum = unionWithRestParameter2(); // error no call signature + +var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; +strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello', 10); // error no call signature +strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature +strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature +strOrNum = unionWithRestParameter3(); // error no call signature \ No newline at end of file From c2b2c306afbe44bd422138e254b2a0db486bc11f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 13:23:06 -0800 Subject: [PATCH 08/41] Tests for union of construct signatures If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U. --- .../unionTypeConstructSignatures.errors.txt | 178 ++++++++++++++++++ .../reference/unionTypeConstructSignatures.js | 132 +++++++++++++ .../union/unionTypeConstructSignatures.ts | 70 +++++++ 3 files changed, 380 insertions(+) create mode 100644 tests/baselines/reference/unionTypeConstructSignatures.errors.txt create mode 100644 tests/baselines/reference/unionTypeConstructSignatures.js create mode 100644 tests/cases/conformance/types/union/unionTypeConstructSignatures.ts diff --git a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt new file mode 100644 index 00000000000..dd46564d779 --- /dev/null +++ b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt @@ -0,0 +1,178 @@ +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(9,47): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(10,33): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(15,33): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(16,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(19,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(20,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(21,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(24,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(25,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(26,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(29,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(30,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(31,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(36,53): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(37,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(40,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(41,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(42,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(43,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(46,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(47,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(48,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(49,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(55,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(56,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(59,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(60,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(61,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(62,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(63,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(66,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(67,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(68,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(69,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + + +==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (35 errors) ==== + var numOrDate: number | Date; + var strOrBoolean: string | boolean; + var strOrNum: string | number; + + // If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, + // U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U. + var unionOfDifferentReturnType: { new (a: number): number; } | { new (a: number): Date; }; + numOrDate = new unionOfDifferentReturnType(10); + strOrBoolean = new unionOfDifferentReturnType("hello"); // error + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + new unionOfDifferentReturnType1(true); // error in type of parameter + ~~~~ +!!! error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'. + + var unionOfDifferentReturnType1: { new (a: number): number; new (a: string): string; } | { new (a: number): Date; new (a: string): boolean; }; + numOrDate = new unionOfDifferentReturnType1(10); + strOrBoolean = new unionOfDifferentReturnType1("hello"); + new unionOfDifferentReturnType1(true); // error in type of parameter + ~~~~ +!!! error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'. + new unionOfDifferentReturnType1(); // error missing parameter + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + var unionOfDifferentParameterTypes: { new (a: number): number; } | { new (a: string): Date; }; + new unionOfDifferentParameterTypes(10);// error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + new unionOfDifferentParameterTypes("hello");// error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + new unionOfDifferentParameterTypes();// error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + + var unionOfDifferentNumberOfSignatures: { new (a: number): number; } | { new (a: number): Date; new (a: string): boolean; }; + new unionOfDifferentNumberOfSignatures(); // error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + new unionOfDifferentNumberOfSignatures(10); // error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + new unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + + var unionWithDifferentParameterCount: { new (a: string): string; } | { new (a: string, b: number): number; }; + new unionWithDifferentParameterCount();// no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + new unionWithDifferentParameterCount("hello");// no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + new unionWithDifferentParameterCount("hello", 10);// no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + + var unionWithOptionalParameter1: { new (a: string, b?: number): string; } | { new (a: string, b?: number): number; }; + strOrNum = new unionWithOptionalParameter1('hello'); + strOrNum = new unionWithOptionalParameter1('hello', 10); + strOrNum = new unionWithOptionalParameter1('hello', "hello"); // error in parameter type + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + strOrNum = new unionWithOptionalParameter1(); // error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + var unionWithOptionalParameter2: { new (a: string, b?: number): string; } | { new (a: string, b: number): number }; + strOrNum = new unionWithOptionalParameter2('hello'); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithOptionalParameter2('hello', 10); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithOptionalParameter2('hello', "hello"); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithOptionalParameter2(); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + + var unionWithOptionalParameter3: { new (a: string, b?: number): string; } | { new (a: string): number; }; + strOrNum = new unionWithOptionalParameter3('hello'); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithOptionalParameter3('hello', 10); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithOptionalParameter3('hello', "hello"); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithOptionalParameter3(); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + + var unionWithRestParameter1: { new (a: string, ...b: number[]): string; } | { new (a: string, ...b: number[]): number }; + strOrNum = new unionWithRestParameter1('hello'); + strOrNum = new unionWithRestParameter1('hello', 10); + strOrNum = new unionWithRestParameter1('hello', 10, 11); + strOrNum = new unionWithRestParameter1('hello', "hello"); // error in parameter type + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + strOrNum = new unionWithRestParameter1(); // error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + var unionWithRestParameter2: { new (a: string, ...b: number[]): string; } | { new (a: string, b: number): number }; + strOrNum = new unionWithRestParameter2('hello'); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithRestParameter2('hello', 10); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithRestParameter2('hello', 10, 11); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithRestParameter2('hello', "hello"); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithRestParameter2(); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + + var unionWithRestParameter3: { new (a: string, ...b: number[]): string; } | { new (a: string): number }; + strOrNum = new unionWithRestParameter3('hello'); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithRestParameter3('hello', 10); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithRestParameter3('hello', 10, 11); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithRestParameter3('hello', "hello"); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + strOrNum = new unionWithRestParameter3(); // error no call signature + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. \ No newline at end of file diff --git a/tests/baselines/reference/unionTypeConstructSignatures.js b/tests/baselines/reference/unionTypeConstructSignatures.js new file mode 100644 index 00000000000..83c3df44603 --- /dev/null +++ b/tests/baselines/reference/unionTypeConstructSignatures.js @@ -0,0 +1,132 @@ +//// [unionTypeConstructSignatures.ts] +var numOrDate: number | Date; +var strOrBoolean: string | boolean; +var strOrNum: string | number; + +// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, +// U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U. +var unionOfDifferentReturnType: { new (a: number): number; } | { new (a: number): Date; }; +numOrDate = new unionOfDifferentReturnType(10); +strOrBoolean = new unionOfDifferentReturnType("hello"); // error +new unionOfDifferentReturnType1(true); // error in type of parameter + +var unionOfDifferentReturnType1: { new (a: number): number; new (a: string): string; } | { new (a: number): Date; new (a: string): boolean; }; +numOrDate = new unionOfDifferentReturnType1(10); +strOrBoolean = new unionOfDifferentReturnType1("hello"); +new unionOfDifferentReturnType1(true); // error in type of parameter +new unionOfDifferentReturnType1(); // error missing parameter + +var unionOfDifferentParameterTypes: { new (a: number): number; } | { new (a: string): Date; }; +new unionOfDifferentParameterTypes(10);// error - no call signatures +new unionOfDifferentParameterTypes("hello");// error - no call signatures +new unionOfDifferentParameterTypes();// error - no call signatures + +var unionOfDifferentNumberOfSignatures: { new (a: number): number; } | { new (a: number): Date; new (a: string): boolean; }; +new unionOfDifferentNumberOfSignatures(); // error - no call signatures +new unionOfDifferentNumberOfSignatures(10); // error - no call signatures +new unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures + +var unionWithDifferentParameterCount: { new (a: string): string; } | { new (a: string, b: number): number; }; +new unionWithDifferentParameterCount();// no call signature +new unionWithDifferentParameterCount("hello");// no call signature +new unionWithDifferentParameterCount("hello", 10);// no call signature + +var unionWithOptionalParameter1: { new (a: string, b?: number): string; } | { new (a: string, b?: number): number; }; +strOrNum = new unionWithOptionalParameter1('hello'); +strOrNum = new unionWithOptionalParameter1('hello', 10); +strOrNum = new unionWithOptionalParameter1('hello', "hello"); // error in parameter type +strOrNum = new unionWithOptionalParameter1(); // error + +var unionWithOptionalParameter2: { new (a: string, b?: number): string; } | { new (a: string, b: number): number }; +strOrNum = new unionWithOptionalParameter2('hello'); // error no call signature +strOrNum = new unionWithOptionalParameter2('hello', 10); // error no call signature +strOrNum = new unionWithOptionalParameter2('hello', "hello"); // error no call signature +strOrNum = new unionWithOptionalParameter2(); // error no call signature + +var unionWithOptionalParameter3: { new (a: string, b?: number): string; } | { new (a: string): number; }; +strOrNum = new unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = new unionWithOptionalParameter3('hello', 10); // error no call signature +strOrNum = new unionWithOptionalParameter3('hello', "hello"); // error no call signature +strOrNum = new unionWithOptionalParameter3(); // error no call signature + +var unionWithRestParameter1: { new (a: string, ...b: number[]): string; } | { new (a: string, ...b: number[]): number }; +strOrNum = new unionWithRestParameter1('hello'); +strOrNum = new unionWithRestParameter1('hello', 10); +strOrNum = new unionWithRestParameter1('hello', 10, 11); +strOrNum = new unionWithRestParameter1('hello', "hello"); // error in parameter type +strOrNum = new unionWithRestParameter1(); // error + +var unionWithRestParameter2: { new (a: string, ...b: number[]): string; } | { new (a: string, b: number): number }; +strOrNum = new unionWithRestParameter2('hello'); // error no call signature +strOrNum = new unionWithRestParameter2('hello', 10); // error no call signature +strOrNum = new unionWithRestParameter2('hello', 10, 11); // error no call signature +strOrNum = new unionWithRestParameter2('hello', "hello"); // error no call signature +strOrNum = new unionWithRestParameter2(); // error no call signature + +var unionWithRestParameter3: { new (a: string, ...b: number[]): string; } | { new (a: string): number }; +strOrNum = new unionWithRestParameter3('hello'); // error no call signature +strOrNum = new unionWithRestParameter3('hello', 10); // error no call signature +strOrNum = new unionWithRestParameter3('hello', 10, 11); // error no call signature +strOrNum = new unionWithRestParameter3('hello', "hello"); // error no call signature +strOrNum = new unionWithRestParameter3(); // error no call signature + +//// [unionTypeConstructSignatures.js] +var numOrDate; +var strOrBoolean; +var strOrNum; +// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, +// U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U. +var unionOfDifferentReturnType; +numOrDate = new unionOfDifferentReturnType(10); +strOrBoolean = new unionOfDifferentReturnType("hello"); // error +new unionOfDifferentReturnType1(true); // error in type of parameter +var unionOfDifferentReturnType1; +numOrDate = new unionOfDifferentReturnType1(10); +strOrBoolean = new unionOfDifferentReturnType1("hello"); +new unionOfDifferentReturnType1(true); // error in type of parameter +new unionOfDifferentReturnType1(); // error missing parameter +var unionOfDifferentParameterTypes; +new unionOfDifferentParameterTypes(10); // error - no call signatures +new unionOfDifferentParameterTypes("hello"); // error - no call signatures +new unionOfDifferentParameterTypes(); // error - no call signatures +var unionOfDifferentNumberOfSignatures; +new unionOfDifferentNumberOfSignatures(); // error - no call signatures +new unionOfDifferentNumberOfSignatures(10); // error - no call signatures +new unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures +var unionWithDifferentParameterCount; +new unionWithDifferentParameterCount(); // no call signature +new unionWithDifferentParameterCount("hello"); // no call signature +new unionWithDifferentParameterCount("hello", 10); // no call signature +var unionWithOptionalParameter1; +strOrNum = new unionWithOptionalParameter1('hello'); +strOrNum = new unionWithOptionalParameter1('hello', 10); +strOrNum = new unionWithOptionalParameter1('hello', "hello"); // error in parameter type +strOrNum = new unionWithOptionalParameter1(); // error +var unionWithOptionalParameter2; +strOrNum = new unionWithOptionalParameter2('hello'); // error no call signature +strOrNum = new unionWithOptionalParameter2('hello', 10); // error no call signature +strOrNum = new unionWithOptionalParameter2('hello', "hello"); // error no call signature +strOrNum = new unionWithOptionalParameter2(); // error no call signature +var unionWithOptionalParameter3; +strOrNum = new unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = new unionWithOptionalParameter3('hello', 10); // error no call signature +strOrNum = new unionWithOptionalParameter3('hello', "hello"); // error no call signature +strOrNum = new unionWithOptionalParameter3(); // error no call signature +var unionWithRestParameter1; +strOrNum = new unionWithRestParameter1('hello'); +strOrNum = new unionWithRestParameter1('hello', 10); +strOrNum = new unionWithRestParameter1('hello', 10, 11); +strOrNum = new unionWithRestParameter1('hello', "hello"); // error in parameter type +strOrNum = new unionWithRestParameter1(); // error +var unionWithRestParameter2; +strOrNum = new unionWithRestParameter2('hello'); // error no call signature +strOrNum = new unionWithRestParameter2('hello', 10); // error no call signature +strOrNum = new unionWithRestParameter2('hello', 10, 11); // error no call signature +strOrNum = new unionWithRestParameter2('hello', "hello"); // error no call signature +strOrNum = new unionWithRestParameter2(); // error no call signature +var unionWithRestParameter3; +strOrNum = new unionWithRestParameter3('hello'); // error no call signature +strOrNum = new unionWithRestParameter3('hello', 10); // error no call signature +strOrNum = new unionWithRestParameter3('hello', 10, 11); // error no call signature +strOrNum = new unionWithRestParameter3('hello', "hello"); // error no call signature +strOrNum = new unionWithRestParameter3(); // error no call signature diff --git a/tests/cases/conformance/types/union/unionTypeConstructSignatures.ts b/tests/cases/conformance/types/union/unionTypeConstructSignatures.ts new file mode 100644 index 00000000000..a02ba610ff7 --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeConstructSignatures.ts @@ -0,0 +1,70 @@ +var numOrDate: number | Date; +var strOrBoolean: string | boolean; +var strOrNum: string | number; + +// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, +// U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U. +var unionOfDifferentReturnType: { new (a: number): number; } | { new (a: number): Date; }; +numOrDate = new unionOfDifferentReturnType(10); +strOrBoolean = new unionOfDifferentReturnType("hello"); // error +new unionOfDifferentReturnType1(true); // error in type of parameter + +var unionOfDifferentReturnType1: { new (a: number): number; new (a: string): string; } | { new (a: number): Date; new (a: string): boolean; }; +numOrDate = new unionOfDifferentReturnType1(10); +strOrBoolean = new unionOfDifferentReturnType1("hello"); +new unionOfDifferentReturnType1(true); // error in type of parameter +new unionOfDifferentReturnType1(); // error missing parameter + +var unionOfDifferentParameterTypes: { new (a: number): number; } | { new (a: string): Date; }; +new unionOfDifferentParameterTypes(10);// error - no call signatures +new unionOfDifferentParameterTypes("hello");// error - no call signatures +new unionOfDifferentParameterTypes();// error - no call signatures + +var unionOfDifferentNumberOfSignatures: { new (a: number): number; } | { new (a: number): Date; new (a: string): boolean; }; +new unionOfDifferentNumberOfSignatures(); // error - no call signatures +new unionOfDifferentNumberOfSignatures(10); // error - no call signatures +new unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures + +var unionWithDifferentParameterCount: { new (a: string): string; } | { new (a: string, b: number): number; }; +new unionWithDifferentParameterCount();// no call signature +new unionWithDifferentParameterCount("hello");// no call signature +new unionWithDifferentParameterCount("hello", 10);// no call signature + +var unionWithOptionalParameter1: { new (a: string, b?: number): string; } | { new (a: string, b?: number): number; }; +strOrNum = new unionWithOptionalParameter1('hello'); +strOrNum = new unionWithOptionalParameter1('hello', 10); +strOrNum = new unionWithOptionalParameter1('hello', "hello"); // error in parameter type +strOrNum = new unionWithOptionalParameter1(); // error + +var unionWithOptionalParameter2: { new (a: string, b?: number): string; } | { new (a: string, b: number): number }; +strOrNum = new unionWithOptionalParameter2('hello'); // error no call signature +strOrNum = new unionWithOptionalParameter2('hello', 10); // error no call signature +strOrNum = new unionWithOptionalParameter2('hello', "hello"); // error no call signature +strOrNum = new unionWithOptionalParameter2(); // error no call signature + +var unionWithOptionalParameter3: { new (a: string, b?: number): string; } | { new (a: string): number; }; +strOrNum = new unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = new unionWithOptionalParameter3('hello', 10); // error no call signature +strOrNum = new unionWithOptionalParameter3('hello', "hello"); // error no call signature +strOrNum = new unionWithOptionalParameter3(); // error no call signature + +var unionWithRestParameter1: { new (a: string, ...b: number[]): string; } | { new (a: string, ...b: number[]): number }; +strOrNum = new unionWithRestParameter1('hello'); +strOrNum = new unionWithRestParameter1('hello', 10); +strOrNum = new unionWithRestParameter1('hello', 10, 11); +strOrNum = new unionWithRestParameter1('hello', "hello"); // error in parameter type +strOrNum = new unionWithRestParameter1(); // error + +var unionWithRestParameter2: { new (a: string, ...b: number[]): string; } | { new (a: string, b: number): number }; +strOrNum = new unionWithRestParameter2('hello'); // error no call signature +strOrNum = new unionWithRestParameter2('hello', 10); // error no call signature +strOrNum = new unionWithRestParameter2('hello', 10, 11); // error no call signature +strOrNum = new unionWithRestParameter2('hello', "hello"); // error no call signature +strOrNum = new unionWithRestParameter2(); // error no call signature + +var unionWithRestParameter3: { new (a: string, ...b: number[]): string; } | { new (a: string): number }; +strOrNum = new unionWithRestParameter3('hello'); // error no call signature +strOrNum = new unionWithRestParameter3('hello', 10); // error no call signature +strOrNum = new unionWithRestParameter3('hello', 10, 11); // error no call signature +strOrNum = new unionWithRestParameter3('hello', "hello"); // error no call signature +strOrNum = new unionWithRestParameter3(); // error no call signature \ No newline at end of file From 49b5b5ab994b3e05924947a8eca2ba43d65cf006 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 13:36:06 -0800 Subject: [PATCH 09/41] =?UTF-8?q?Tests=20for=20union=20of=20index=20signat?= =?UTF-8?q?ures:=20=E2=80=A2=09If=20each=20type=20in=20U=20has=20a=20strin?= =?UTF-8?q?g=20index=20signature,=20U=20has=20a=20string=20index=20signatu?= =?UTF-8?q?re=20of=20a=20union=20type=20of=20the=20types=20of=20the=20stri?= =?UTF-8?q?ng=20index=20signatures=20from=20each=20type=20in=20U.=20?= =?UTF-8?q?=E2=80=A2=09If=20each=20type=20in=20U=20has=20a=20numeric=20ind?= =?UTF-8?q?ex=20signature,=20U=20has=20a=20numeric=20index=20signature=20o?= =?UTF-8?q?f=20a=20union=20type=20of=20the=20types=20of=20the=20numeric=20?= =?UTF-8?q?index=20signatures=20from=20each=20type=20in=20U.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/unionTypeIndexSignature.js | 44 ++++++++++ .../reference/unionTypeIndexSignature.types | 81 +++++++++++++++++++ .../types/union/unionTypeIndexSignature.ts | 23 ++++++ 3 files changed, 148 insertions(+) create mode 100644 tests/baselines/reference/unionTypeIndexSignature.js create mode 100644 tests/baselines/reference/unionTypeIndexSignature.types create mode 100644 tests/cases/conformance/types/union/unionTypeIndexSignature.ts diff --git a/tests/baselines/reference/unionTypeIndexSignature.js b/tests/baselines/reference/unionTypeIndexSignature.js new file mode 100644 index 00000000000..b39a42e76a4 --- /dev/null +++ b/tests/baselines/reference/unionTypeIndexSignature.js @@ -0,0 +1,44 @@ +//// [unionTypeIndexSignature.ts] +var numOrDate: number | Date; +var anyVar: number; + +// If each type in U has a string index signature, +// U has a string index signature of a union type of the types of the string index signatures from each type in U. + +var unionOfDifferentReturnType: { [a: string]: number; } | { [a: string]: Date; }; +numOrDate = unionOfDifferentReturnType["hello"]; // number | Date +numOrDate = unionOfDifferentReturnType[10]; // number | Date + +var unionOfTypesWithAndWithoutStringSignature: { [a: string]: number; } | boolean; +anyVar = unionOfTypesWithAndWithoutStringSignature["hello"]; // any +anyVar = unionOfTypesWithAndWithoutStringSignature[10]; // any + +// If each type in U has a numeric index signature, +// U has a numeric index signature of a union type of the types of the numeric index signatures from each type in U. +var unionOfDifferentReturnType1: { [a: number]: number; } | { [a: number]: Date; }; +numOrDate = unionOfDifferentReturnType1["hello"]; // any +numOrDate = unionOfDifferentReturnType1[10]; // number | Date + +var unionOfTypesWithAndWithoutStringSignature1: { [a: number]: number; } | boolean; +anyVar = unionOfTypesWithAndWithoutStringSignature1["hello"]; // any +anyVar = unionOfTypesWithAndWithoutStringSignature1[10]; // any + +//// [unionTypeIndexSignature.js] +var numOrDate; +var anyVar; +// If each type in U has a string index signature, +// U has a string index signature of a union type of the types of the string index signatures from each type in U. +var unionOfDifferentReturnType; +numOrDate = unionOfDifferentReturnType["hello"]; // number | Date +numOrDate = unionOfDifferentReturnType[10]; // number | Date +var unionOfTypesWithAndWithoutStringSignature; +anyVar = unionOfTypesWithAndWithoutStringSignature["hello"]; // any +anyVar = unionOfTypesWithAndWithoutStringSignature[10]; // any +// If each type in U has a numeric index signature, +// U has a numeric index signature of a union type of the types of the numeric index signatures from each type in U. +var unionOfDifferentReturnType1; +numOrDate = unionOfDifferentReturnType1["hello"]; // any +numOrDate = unionOfDifferentReturnType1[10]; // number | Date +var unionOfTypesWithAndWithoutStringSignature1; +anyVar = unionOfTypesWithAndWithoutStringSignature1["hello"]; // any +anyVar = unionOfTypesWithAndWithoutStringSignature1[10]; // any diff --git a/tests/baselines/reference/unionTypeIndexSignature.types b/tests/baselines/reference/unionTypeIndexSignature.types new file mode 100644 index 00000000000..96453cffcb4 --- /dev/null +++ b/tests/baselines/reference/unionTypeIndexSignature.types @@ -0,0 +1,81 @@ +=== tests/cases/conformance/types/union/unionTypeIndexSignature.ts === +var numOrDate: number | Date; +>numOrDate : number | Date +>Date : Date + +var anyVar: number; +>anyVar : number + +// If each type in U has a string index signature, +// U has a string index signature of a union type of the types of the string index signatures from each type in U. + +var unionOfDifferentReturnType: { [a: string]: number; } | { [a: string]: Date; }; +>unionOfDifferentReturnType : { [x: string]: number; } | { [x: string]: Date; } +>a : string +>a : string +>Date : Date + +numOrDate = unionOfDifferentReturnType["hello"]; // number | Date +>numOrDate = unionOfDifferentReturnType["hello"] : number | Date +>numOrDate : number | Date +>unionOfDifferentReturnType["hello"] : number | Date +>unionOfDifferentReturnType : { [x: string]: number; } | { [x: string]: Date; } + +numOrDate = unionOfDifferentReturnType[10]; // number | Date +>numOrDate = unionOfDifferentReturnType[10] : number | Date +>numOrDate : number | Date +>unionOfDifferentReturnType[10] : number | Date +>unionOfDifferentReturnType : { [x: string]: number; } | { [x: string]: Date; } + +var unionOfTypesWithAndWithoutStringSignature: { [a: string]: number; } | boolean; +>unionOfTypesWithAndWithoutStringSignature : boolean | { [x: string]: number; } +>a : string + +anyVar = unionOfTypesWithAndWithoutStringSignature["hello"]; // any +>anyVar = unionOfTypesWithAndWithoutStringSignature["hello"] : any +>anyVar : number +>unionOfTypesWithAndWithoutStringSignature["hello"] : any +>unionOfTypesWithAndWithoutStringSignature : boolean | { [x: string]: number; } + +anyVar = unionOfTypesWithAndWithoutStringSignature[10]; // any +>anyVar = unionOfTypesWithAndWithoutStringSignature[10] : any +>anyVar : number +>unionOfTypesWithAndWithoutStringSignature[10] : any +>unionOfTypesWithAndWithoutStringSignature : boolean | { [x: string]: number; } + +// If each type in U has a numeric index signature, +// U has a numeric index signature of a union type of the types of the numeric index signatures from each type in U. +var unionOfDifferentReturnType1: { [a: number]: number; } | { [a: number]: Date; }; +>unionOfDifferentReturnType1 : { [x: number]: number; } | { [x: number]: Date; } +>a : number +>a : number +>Date : Date + +numOrDate = unionOfDifferentReturnType1["hello"]; // any +>numOrDate = unionOfDifferentReturnType1["hello"] : any +>numOrDate : number | Date +>unionOfDifferentReturnType1["hello"] : any +>unionOfDifferentReturnType1 : { [x: number]: number; } | { [x: number]: Date; } + +numOrDate = unionOfDifferentReturnType1[10]; // number | Date +>numOrDate = unionOfDifferentReturnType1[10] : number | Date +>numOrDate : number | Date +>unionOfDifferentReturnType1[10] : number | Date +>unionOfDifferentReturnType1 : { [x: number]: number; } | { [x: number]: Date; } + +var unionOfTypesWithAndWithoutStringSignature1: { [a: number]: number; } | boolean; +>unionOfTypesWithAndWithoutStringSignature1 : boolean | { [x: number]: number; } +>a : number + +anyVar = unionOfTypesWithAndWithoutStringSignature1["hello"]; // any +>anyVar = unionOfTypesWithAndWithoutStringSignature1["hello"] : any +>anyVar : number +>unionOfTypesWithAndWithoutStringSignature1["hello"] : any +>unionOfTypesWithAndWithoutStringSignature1 : boolean | { [x: number]: number; } + +anyVar = unionOfTypesWithAndWithoutStringSignature1[10]; // any +>anyVar = unionOfTypesWithAndWithoutStringSignature1[10] : any +>anyVar : number +>unionOfTypesWithAndWithoutStringSignature1[10] : any +>unionOfTypesWithAndWithoutStringSignature1 : boolean | { [x: number]: number; } + diff --git a/tests/cases/conformance/types/union/unionTypeIndexSignature.ts b/tests/cases/conformance/types/union/unionTypeIndexSignature.ts new file mode 100644 index 00000000000..698da7449f4 --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeIndexSignature.ts @@ -0,0 +1,23 @@ +var numOrDate: number | Date; +var anyVar: number; + +// If each type in U has a string index signature, +// U has a string index signature of a union type of the types of the string index signatures from each type in U. + +var unionOfDifferentReturnType: { [a: string]: number; } | { [a: string]: Date; }; +numOrDate = unionOfDifferentReturnType["hello"]; // number | Date +numOrDate = unionOfDifferentReturnType[10]; // number | Date + +var unionOfTypesWithAndWithoutStringSignature: { [a: string]: number; } | boolean; +anyVar = unionOfTypesWithAndWithoutStringSignature["hello"]; // any +anyVar = unionOfTypesWithAndWithoutStringSignature[10]; // any + +// If each type in U has a numeric index signature, +// U has a numeric index signature of a union type of the types of the numeric index signatures from each type in U. +var unionOfDifferentReturnType1: { [a: number]: number; } | { [a: number]: Date; }; +numOrDate = unionOfDifferentReturnType1["hello"]; // any +numOrDate = unionOfDifferentReturnType1[10]; // number | Date + +var unionOfTypesWithAndWithoutStringSignature1: { [a: number]: number; } | boolean; +anyVar = unionOfTypesWithAndWithoutStringSignature1["hello"]; // any +anyVar = unionOfTypesWithAndWithoutStringSignature1[10]; // any \ No newline at end of file From b66cd9b0fc9d69d82c2142fdc14e2352e560a499 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 15:59:57 -0800 Subject: [PATCH 10/41] Results of || operation produces union type --- .../logicalOrOperatorWithEveryType.js | 160 +++++++++--------- .../logicalOrOperatorWithEveryType.types | 80 ++++----- .../logicalOrOperatorWithEveryType.ts | 80 ++++----- 3 files changed, 160 insertions(+), 160 deletions(-) diff --git a/tests/baselines/reference/logicalOrOperatorWithEveryType.js b/tests/baselines/reference/logicalOrOperatorWithEveryType.js index bf7a641882e..78601374c22 100644 --- a/tests/baselines/reference/logicalOrOperatorWithEveryType.js +++ b/tests/baselines/reference/logicalOrOperatorWithEveryType.js @@ -28,77 +28,77 @@ var ra10 = undefined || a1; // undefined || any is any var rb1 = a1 || a2; // any || boolean is any var rb2 = a2 || a2; // boolean || boolean is boolean -var rb3 = a3 || a2; // number || boolean is {} -var rb4 = a4 || a2; // string || boolean is {} -var rb5 = a5 || a2; // void || boolean is {} -var rb6 = a6 || a2; // enum || boolean is {} -var rb7 = a7 || a2; // object || boolean is {} -var rb8 = a8 || a2; // array || boolean is {} +var rb3 = a3 || a2; // number || boolean is number | boolean +var rb4 = a4 || a2; // string || boolean is string | boolean +var rb5 = a5 || a2; // void || boolean is void | boolean +var rb6 = a6 || a2; // enum || boolean is E | boolean +var rb7 = a7 || a2; // object || boolean is object | boolean +var rb8 = a8 || a2; // array || boolean is array | boolean var rb9 = null || a2; // null || boolean is boolean var rb10= undefined || a2; // undefined || boolean is boolean var rc1 = a1 || a3; // any || number is any -var rc2 = a2 || a3; // boolean || number is {} +var rc2 = a2 || a3; // boolean || number is boolean | number var rc3 = a3 || a3; // number || number is number -var rc4 = a4 || a3; // string || number is {} -var rc5 = a5 || a3; // void || number is {} +var rc4 = a4 || a3; // string || number is string | number +var rc5 = a5 || a3; // void || number is void | number var rc6 = a6 || a3; // enum || number is number -var rc7 = a7 || a3; // object || number is {} -var rc8 = a8 || a3; // array || number is {} +var rc7 = a7 || a3; // object || number is object | number +var rc8 = a8 || a3; // array || number is array | number var rc9 = null || a3; // null || number is number var rc10 = undefined || a3; // undefined || number is number var rd1 = a1 || a4; // any || string is any -var rd2 = a2 || a4; // boolean || string is {} -var rd3 = a3 || a4; // number || string is {} +var rd2 = a2 || a4; // boolean || string is boolean | string +var rd3 = a3 || a4; // number || string is number | string var rd4 = a4 || a4; // string || string is string -var rd5 = a5 || a4; // void || string is {} -var rd6 = a6 || a4; // enum || string is {} -var rd7 = a7 || a4; // object || string is {} -var rd8 = a8 || a4; // array || string is {} +var rd5 = a5 || a4; // void || string is void | string +var rd6 = a6 || a4; // enum || string is enum | string +var rd7 = a7 || a4; // object || string is object | string +var rd8 = a8 || a4; // array || string is array | string var rd9 = null || a4; // null || string is string var rd10 = undefined || a4; // undefined || string is string var re1 = a1 || a5; // any || void is any -var re2 = a2 || a5; // boolean || void is {} -var re3 = a3 || a5; // number || void is {} -var re4 = a4 || a5; // string || void is {} +var re2 = a2 || a5; // boolean || void is boolean | void +var re3 = a3 || a5; // number || void is number | void +var re4 = a4 || a5; // string || void is string | void var re5 = a5 || a5; // void || void is void -var re6 = a6 || a5; // enum || void is {} -var re7 = a7 || a5; // object || void is {} -var re8 = a8 || a5; // array || void is {} +var re6 = a6 || a5; // enum || void is enum | void +var re7 = a7 || a5; // object || void is object | void +var re8 = a8 || a5; // array || void is array | void var re9 = null || a5; // null || void is void var re10 = undefined || a5; // undefined || void is void var rg1 = a1 || a6; // any || enum is any -var rg2 = a2 || a6; // boolean || enum is {} +var rg2 = a2 || a6; // boolean || enum is boolean | enum var rg3 = a3 || a6; // number || enum is number -var rg4 = a4 || a6; // string || enum is {} -var rg5 = a5 || a6; // void || enum is {} +var rg4 = a4 || a6; // string || enum is string | enum +var rg5 = a5 || a6; // void || enum is void | enum var rg6 = a6 || a6; // enum || enum is E -var rg7 = a7 || a6; // object || enum is {} -var rg8 = a8 || a6; // array || enum is {} +var rg7 = a7 || a6; // object || enum is object | enum +var rg8 = a8 || a6; // array || enum is array | enum var rg9 = null || a6; // null || enum is E var rg10 = undefined || a6; // undefined || enum is E var rh1 = a1 || a7; // any || object is any -var rh2 = a2 || a7; // boolean || object is {} -var rh3 = a3 || a7; // number || object is {} -var rh4 = a4 || a7; // string || object is {} -var rh5 = a5 || a7; // void || object is {} -var rh6 = a6 || a7; // enum || object is {} +var rh2 = a2 || a7; // boolean || object is boolean | object +var rh3 = a3 || a7; // number || object is number | object +var rh4 = a4 || a7; // string || object is string | object +var rh5 = a5 || a7; // void || object is void | object +var rh6 = a6 || a7; // enum || object is enum | object var rh7 = a7 || a7; // object || object is object -var rh8 = a8 || a7; // array || object is {} +var rh8 = a8 || a7; // array || object is array | object var rh9 = null || a7; // null || object is object var rh10 = undefined || a7; // undefined || object is object var ri1 = a1 || a8; // any || array is any -var ri2 = a2 || a8; // boolean || array is {} -var ri3 = a3 || a8; // number || array is {} -var ri4 = a4 || a8; // string || array is {} -var ri5 = a5 || a8; // void || array is {} -var ri6 = a6 || a8; // enum || array is {} -var ri7 = a7 || a8; // object || array is {} +var ri2 = a2 || a8; // boolean || array is boolean | array +var ri3 = a3 || a8; // number || array is number | array +var ri4 = a4 || a8; // string || array is string | array +var ri5 = a5 || a8; // void || array is void | array +var ri6 = a6 || a8; // enum || array is enum | array +var ri7 = a7 || a8; // object || array is object | array var ri8 = a8 || a8; // array || array is array var ri9 = null || a8; // null || array is array var ri10 = undefined || a8; // undefined || array is array @@ -156,71 +156,71 @@ var ra9 = null || a1; // null || any is any var ra10 = undefined || a1; // undefined || any is any var rb1 = a1 || a2; // any || boolean is any var rb2 = a2 || a2; // boolean || boolean is boolean -var rb3 = a3 || a2; // number || boolean is {} -var rb4 = a4 || a2; // string || boolean is {} -var rb5 = a5 || a2; // void || boolean is {} -var rb6 = a6 || a2; // enum || boolean is {} -var rb7 = a7 || a2; // object || boolean is {} -var rb8 = a8 || a2; // array || boolean is {} +var rb3 = a3 || a2; // number || boolean is number | boolean +var rb4 = a4 || a2; // string || boolean is string | boolean +var rb5 = a5 || a2; // void || boolean is void | boolean +var rb6 = a6 || a2; // enum || boolean is E | boolean +var rb7 = a7 || a2; // object || boolean is object | boolean +var rb8 = a8 || a2; // array || boolean is array | boolean var rb9 = null || a2; // null || boolean is boolean var rb10 = undefined || a2; // undefined || boolean is boolean var rc1 = a1 || a3; // any || number is any -var rc2 = a2 || a3; // boolean || number is {} +var rc2 = a2 || a3; // boolean || number is boolean | number var rc3 = a3 || a3; // number || number is number -var rc4 = a4 || a3; // string || number is {} -var rc5 = a5 || a3; // void || number is {} +var rc4 = a4 || a3; // string || number is string | number +var rc5 = a5 || a3; // void || number is void | number var rc6 = a6 || a3; // enum || number is number -var rc7 = a7 || a3; // object || number is {} -var rc8 = a8 || a3; // array || number is {} +var rc7 = a7 || a3; // object || number is object | number +var rc8 = a8 || a3; // array || number is array | number var rc9 = null || a3; // null || number is number var rc10 = undefined || a3; // undefined || number is number var rd1 = a1 || a4; // any || string is any -var rd2 = a2 || a4; // boolean || string is {} -var rd3 = a3 || a4; // number || string is {} +var rd2 = a2 || a4; // boolean || string is boolean | string +var rd3 = a3 || a4; // number || string is number | string var rd4 = a4 || a4; // string || string is string -var rd5 = a5 || a4; // void || string is {} -var rd6 = a6 || a4; // enum || string is {} -var rd7 = a7 || a4; // object || string is {} -var rd8 = a8 || a4; // array || string is {} +var rd5 = a5 || a4; // void || string is void | string +var rd6 = a6 || a4; // enum || string is enum | string +var rd7 = a7 || a4; // object || string is object | string +var rd8 = a8 || a4; // array || string is array | string var rd9 = null || a4; // null || string is string var rd10 = undefined || a4; // undefined || string is string var re1 = a1 || a5; // any || void is any -var re2 = a2 || a5; // boolean || void is {} -var re3 = a3 || a5; // number || void is {} -var re4 = a4 || a5; // string || void is {} +var re2 = a2 || a5; // boolean || void is boolean | void +var re3 = a3 || a5; // number || void is number | void +var re4 = a4 || a5; // string || void is string | void var re5 = a5 || a5; // void || void is void -var re6 = a6 || a5; // enum || void is {} -var re7 = a7 || a5; // object || void is {} -var re8 = a8 || a5; // array || void is {} +var re6 = a6 || a5; // enum || void is enum | void +var re7 = a7 || a5; // object || void is object | void +var re8 = a8 || a5; // array || void is array | void var re9 = null || a5; // null || void is void var re10 = undefined || a5; // undefined || void is void var rg1 = a1 || a6; // any || enum is any -var rg2 = a2 || a6; // boolean || enum is {} +var rg2 = a2 || a6; // boolean || enum is boolean | enum var rg3 = a3 || a6; // number || enum is number -var rg4 = a4 || a6; // string || enum is {} -var rg5 = a5 || a6; // void || enum is {} +var rg4 = a4 || a6; // string || enum is string | enum +var rg5 = a5 || a6; // void || enum is void | enum var rg6 = a6 || a6; // enum || enum is E -var rg7 = a7 || a6; // object || enum is {} -var rg8 = a8 || a6; // array || enum is {} +var rg7 = a7 || a6; // object || enum is object | enum +var rg8 = a8 || a6; // array || enum is array | enum var rg9 = null || a6; // null || enum is E var rg10 = undefined || a6; // undefined || enum is E var rh1 = a1 || a7; // any || object is any -var rh2 = a2 || a7; // boolean || object is {} -var rh3 = a3 || a7; // number || object is {} -var rh4 = a4 || a7; // string || object is {} -var rh5 = a5 || a7; // void || object is {} -var rh6 = a6 || a7; // enum || object is {} +var rh2 = a2 || a7; // boolean || object is boolean | object +var rh3 = a3 || a7; // number || object is number | object +var rh4 = a4 || a7; // string || object is string | object +var rh5 = a5 || a7; // void || object is void | object +var rh6 = a6 || a7; // enum || object is enum | object var rh7 = a7 || a7; // object || object is object -var rh8 = a8 || a7; // array || object is {} +var rh8 = a8 || a7; // array || object is array | object var rh9 = null || a7; // null || object is object var rh10 = undefined || a7; // undefined || object is object var ri1 = a1 || a8; // any || array is any -var ri2 = a2 || a8; // boolean || array is {} -var ri3 = a3 || a8; // number || array is {} -var ri4 = a4 || a8; // string || array is {} -var ri5 = a5 || a8; // void || array is {} -var ri6 = a6 || a8; // enum || array is {} -var ri7 = a7 || a8; // object || array is {} +var ri2 = a2 || a8; // boolean || array is boolean | array +var ri3 = a3 || a8; // number || array is number | array +var ri4 = a4 || a8; // string || array is string | array +var ri5 = a5 || a8; // void || array is void | array +var ri6 = a6 || a8; // enum || array is enum | array +var ri7 = a7 || a8; // object || array is object | array var ri8 = a8 || a8; // array || array is array var ri9 = null || a8; // null || array is array var ri10 = undefined || a8; // undefined || array is array diff --git a/tests/baselines/reference/logicalOrOperatorWithEveryType.types b/tests/baselines/reference/logicalOrOperatorWithEveryType.types index 3e3b0dcf37f..ae8dab8c71c 100644 --- a/tests/baselines/reference/logicalOrOperatorWithEveryType.types +++ b/tests/baselines/reference/logicalOrOperatorWithEveryType.types @@ -107,37 +107,37 @@ var rb2 = a2 || a2; // boolean || boolean is boolean >a2 : boolean >a2 : boolean -var rb3 = a3 || a2; // number || boolean is {} +var rb3 = a3 || a2; // number || boolean is number | boolean >rb3 : number | boolean >a3 || a2 : number | boolean >a3 : number >a2 : boolean -var rb4 = a4 || a2; // string || boolean is {} +var rb4 = a4 || a2; // string || boolean is string | boolean >rb4 : string | boolean >a4 || a2 : string | boolean >a4 : string >a2 : boolean -var rb5 = a5 || a2; // void || boolean is {} +var rb5 = a5 || a2; // void || boolean is void | boolean >rb5 : boolean | void >a5 || a2 : boolean | void >a5 : void >a2 : boolean -var rb6 = a6 || a2; // enum || boolean is {} +var rb6 = a6 || a2; // enum || boolean is E | boolean >rb6 : boolean | E >a6 || a2 : boolean | E >a6 : E >a2 : boolean -var rb7 = a7 || a2; // object || boolean is {} +var rb7 = a7 || a2; // object || boolean is object | boolean >rb7 : boolean | { a: string; } >a7 || a2 : boolean | { a: string; } >a7 : { a: string; } >a2 : boolean -var rb8 = a8 || a2; // array || boolean is {} +var rb8 = a8 || a2; // array || boolean is array | boolean >rb8 : boolean | string[] >a8 || a2 : boolean | string[] >a8 : string[] @@ -160,7 +160,7 @@ var rc1 = a1 || a3; // any || number is any >a1 : any >a3 : number -var rc2 = a2 || a3; // boolean || number is {} +var rc2 = a2 || a3; // boolean || number is boolean | number >rc2 : number | boolean >a2 || a3 : number | boolean >a2 : boolean @@ -172,13 +172,13 @@ var rc3 = a3 || a3; // number || number is number >a3 : number >a3 : number -var rc4 = a4 || a3; // string || number is {} +var rc4 = a4 || a3; // string || number is string | number >rc4 : string | number >a4 || a3 : string | number >a4 : string >a3 : number -var rc5 = a5 || a3; // void || number is {} +var rc5 = a5 || a3; // void || number is void | number >rc5 : number | void >a5 || a3 : number | void >a5 : void @@ -190,13 +190,13 @@ var rc6 = a6 || a3; // enum || number is number >a6 : E >a3 : number -var rc7 = a7 || a3; // object || number is {} +var rc7 = a7 || a3; // object || number is object | number >rc7 : number | { a: string; } >a7 || a3 : number | { a: string; } >a7 : { a: string; } >a3 : number -var rc8 = a8 || a3; // array || number is {} +var rc8 = a8 || a3; // array || number is array | number >rc8 : number | string[] >a8 || a3 : number | string[] >a8 : string[] @@ -219,13 +219,13 @@ var rd1 = a1 || a4; // any || string is any >a1 : any >a4 : string -var rd2 = a2 || a4; // boolean || string is {} +var rd2 = a2 || a4; // boolean || string is boolean | string >rd2 : string | boolean >a2 || a4 : string | boolean >a2 : boolean >a4 : string -var rd3 = a3 || a4; // number || string is {} +var rd3 = a3 || a4; // number || string is number | string >rd3 : string | number >a3 || a4 : string | number >a3 : number @@ -237,25 +237,25 @@ var rd4 = a4 || a4; // string || string is string >a4 : string >a4 : string -var rd5 = a5 || a4; // void || string is {} +var rd5 = a5 || a4; // void || string is void | string >rd5 : string | void >a5 || a4 : string | void >a5 : void >a4 : string -var rd6 = a6 || a4; // enum || string is {} +var rd6 = a6 || a4; // enum || string is enum | string >rd6 : string | E >a6 || a4 : string | E >a6 : E >a4 : string -var rd7 = a7 || a4; // object || string is {} +var rd7 = a7 || a4; // object || string is object | string >rd7 : string | { a: string; } >a7 || a4 : string | { a: string; } >a7 : { a: string; } >a4 : string -var rd8 = a8 || a4; // array || string is {} +var rd8 = a8 || a4; // array || string is array | string >rd8 : string | string[] >a8 || a4 : string | string[] >a8 : string[] @@ -278,19 +278,19 @@ var re1 = a1 || a5; // any || void is any >a1 : any >a5 : void -var re2 = a2 || a5; // boolean || void is {} +var re2 = a2 || a5; // boolean || void is boolean | void >re2 : boolean | void >a2 || a5 : boolean | void >a2 : boolean >a5 : void -var re3 = a3 || a5; // number || void is {} +var re3 = a3 || a5; // number || void is number | void >re3 : number | void >a3 || a5 : number | void >a3 : number >a5 : void -var re4 = a4 || a5; // string || void is {} +var re4 = a4 || a5; // string || void is string | void >re4 : string | void >a4 || a5 : string | void >a4 : string @@ -302,19 +302,19 @@ var re5 = a5 || a5; // void || void is void >a5 : void >a5 : void -var re6 = a6 || a5; // enum || void is {} +var re6 = a6 || a5; // enum || void is enum | void >re6 : void | E >a6 || a5 : void | E >a6 : E >a5 : void -var re7 = a7 || a5; // object || void is {} +var re7 = a7 || a5; // object || void is object | void >re7 : void | { a: string; } >a7 || a5 : void | { a: string; } >a7 : { a: string; } >a5 : void -var re8 = a8 || a5; // array || void is {} +var re8 = a8 || a5; // array || void is array | void >re8 : void | string[] >a8 || a5 : void | string[] >a8 : string[] @@ -337,7 +337,7 @@ var rg1 = a1 || a6; // any || enum is any >a1 : any >a6 : E -var rg2 = a2 || a6; // boolean || enum is {} +var rg2 = a2 || a6; // boolean || enum is boolean | enum >rg2 : boolean | E >a2 || a6 : boolean | E >a2 : boolean @@ -349,13 +349,13 @@ var rg3 = a3 || a6; // number || enum is number >a3 : number >a6 : E -var rg4 = a4 || a6; // string || enum is {} +var rg4 = a4 || a6; // string || enum is string | enum >rg4 : string | E >a4 || a6 : string | E >a4 : string >a6 : E -var rg5 = a5 || a6; // void || enum is {} +var rg5 = a5 || a6; // void || enum is void | enum >rg5 : void | E >a5 || a6 : void | E >a5 : void @@ -367,13 +367,13 @@ var rg6 = a6 || a6; // enum || enum is E >a6 : E >a6 : E -var rg7 = a7 || a6; // object || enum is {} +var rg7 = a7 || a6; // object || enum is object | enum >rg7 : E | { a: string; } >a7 || a6 : E | { a: string; } >a7 : { a: string; } >a6 : E -var rg8 = a8 || a6; // array || enum is {} +var rg8 = a8 || a6; // array || enum is array | enum >rg8 : string[] | E >a8 || a6 : string[] | E >a8 : string[] @@ -396,31 +396,31 @@ var rh1 = a1 || a7; // any || object is any >a1 : any >a7 : { a: string; } -var rh2 = a2 || a7; // boolean || object is {} +var rh2 = a2 || a7; // boolean || object is boolean | object >rh2 : boolean | { a: string; } >a2 || a7 : boolean | { a: string; } >a2 : boolean >a7 : { a: string; } -var rh3 = a3 || a7; // number || object is {} +var rh3 = a3 || a7; // number || object is number | object >rh3 : number | { a: string; } >a3 || a7 : number | { a: string; } >a3 : number >a7 : { a: string; } -var rh4 = a4 || a7; // string || object is {} +var rh4 = a4 || a7; // string || object is string | object >rh4 : string | { a: string; } >a4 || a7 : string | { a: string; } >a4 : string >a7 : { a: string; } -var rh5 = a5 || a7; // void || object is {} +var rh5 = a5 || a7; // void || object is void | object >rh5 : void | { a: string; } >a5 || a7 : void | { a: string; } >a5 : void >a7 : { a: string; } -var rh6 = a6 || a7; // enum || object is {} +var rh6 = a6 || a7; // enum || object is enum | object >rh6 : E | { a: string; } >a6 || a7 : E | { a: string; } >a6 : E @@ -432,7 +432,7 @@ var rh7 = a7 || a7; // object || object is object >a7 : { a: string; } >a7 : { a: string; } -var rh8 = a8 || a7; // array || object is {} +var rh8 = a8 || a7; // array || object is array | object >rh8 : string[] | { a: string; } >a8 || a7 : string[] | { a: string; } >a8 : string[] @@ -455,37 +455,37 @@ var ri1 = a1 || a8; // any || array is any >a1 : any >a8 : string[] -var ri2 = a2 || a8; // boolean || array is {} +var ri2 = a2 || a8; // boolean || array is boolean | array >ri2 : boolean | string[] >a2 || a8 : boolean | string[] >a2 : boolean >a8 : string[] -var ri3 = a3 || a8; // number || array is {} +var ri3 = a3 || a8; // number || array is number | array >ri3 : number | string[] >a3 || a8 : number | string[] >a3 : number >a8 : string[] -var ri4 = a4 || a8; // string || array is {} +var ri4 = a4 || a8; // string || array is string | array >ri4 : string | string[] >a4 || a8 : string | string[] >a4 : string >a8 : string[] -var ri5 = a5 || a8; // void || array is {} +var ri5 = a5 || a8; // void || array is void | array >ri5 : void | string[] >a5 || a8 : void | string[] >a5 : void >a8 : string[] -var ri6 = a6 || a8; // enum || array is {} +var ri6 = a6 || a8; // enum || array is enum | array >ri6 : string[] | E >a6 || a8 : string[] | E >a6 : E >a8 : string[] -var ri7 = a7 || a8; // object || array is {} +var ri7 = a7 || a8; // object || array is object | array >ri7 : string[] | { a: string; } >a7 || a8 : string[] | { a: string; } >a7 : { a: string; } diff --git a/tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts b/tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts index 2db2b854f6a..9ec124449f3 100644 --- a/tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts +++ b/tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts @@ -27,77 +27,77 @@ var ra10 = undefined || a1; // undefined || any is any var rb1 = a1 || a2; // any || boolean is any var rb2 = a2 || a2; // boolean || boolean is boolean -var rb3 = a3 || a2; // number || boolean is {} -var rb4 = a4 || a2; // string || boolean is {} -var rb5 = a5 || a2; // void || boolean is {} -var rb6 = a6 || a2; // enum || boolean is {} -var rb7 = a7 || a2; // object || boolean is {} -var rb8 = a8 || a2; // array || boolean is {} +var rb3 = a3 || a2; // number || boolean is number | boolean +var rb4 = a4 || a2; // string || boolean is string | boolean +var rb5 = a5 || a2; // void || boolean is void | boolean +var rb6 = a6 || a2; // enum || boolean is E | boolean +var rb7 = a7 || a2; // object || boolean is object | boolean +var rb8 = a8 || a2; // array || boolean is array | boolean var rb9 = null || a2; // null || boolean is boolean var rb10= undefined || a2; // undefined || boolean is boolean var rc1 = a1 || a3; // any || number is any -var rc2 = a2 || a3; // boolean || number is {} +var rc2 = a2 || a3; // boolean || number is boolean | number var rc3 = a3 || a3; // number || number is number -var rc4 = a4 || a3; // string || number is {} -var rc5 = a5 || a3; // void || number is {} +var rc4 = a4 || a3; // string || number is string | number +var rc5 = a5 || a3; // void || number is void | number var rc6 = a6 || a3; // enum || number is number -var rc7 = a7 || a3; // object || number is {} -var rc8 = a8 || a3; // array || number is {} +var rc7 = a7 || a3; // object || number is object | number +var rc8 = a8 || a3; // array || number is array | number var rc9 = null || a3; // null || number is number var rc10 = undefined || a3; // undefined || number is number var rd1 = a1 || a4; // any || string is any -var rd2 = a2 || a4; // boolean || string is {} -var rd3 = a3 || a4; // number || string is {} +var rd2 = a2 || a4; // boolean || string is boolean | string +var rd3 = a3 || a4; // number || string is number | string var rd4 = a4 || a4; // string || string is string -var rd5 = a5 || a4; // void || string is {} -var rd6 = a6 || a4; // enum || string is {} -var rd7 = a7 || a4; // object || string is {} -var rd8 = a8 || a4; // array || string is {} +var rd5 = a5 || a4; // void || string is void | string +var rd6 = a6 || a4; // enum || string is enum | string +var rd7 = a7 || a4; // object || string is object | string +var rd8 = a8 || a4; // array || string is array | string var rd9 = null || a4; // null || string is string var rd10 = undefined || a4; // undefined || string is string var re1 = a1 || a5; // any || void is any -var re2 = a2 || a5; // boolean || void is {} -var re3 = a3 || a5; // number || void is {} -var re4 = a4 || a5; // string || void is {} +var re2 = a2 || a5; // boolean || void is boolean | void +var re3 = a3 || a5; // number || void is number | void +var re4 = a4 || a5; // string || void is string | void var re5 = a5 || a5; // void || void is void -var re6 = a6 || a5; // enum || void is {} -var re7 = a7 || a5; // object || void is {} -var re8 = a8 || a5; // array || void is {} +var re6 = a6 || a5; // enum || void is enum | void +var re7 = a7 || a5; // object || void is object | void +var re8 = a8 || a5; // array || void is array | void var re9 = null || a5; // null || void is void var re10 = undefined || a5; // undefined || void is void var rg1 = a1 || a6; // any || enum is any -var rg2 = a2 || a6; // boolean || enum is {} +var rg2 = a2 || a6; // boolean || enum is boolean | enum var rg3 = a3 || a6; // number || enum is number -var rg4 = a4 || a6; // string || enum is {} -var rg5 = a5 || a6; // void || enum is {} +var rg4 = a4 || a6; // string || enum is string | enum +var rg5 = a5 || a6; // void || enum is void | enum var rg6 = a6 || a6; // enum || enum is E -var rg7 = a7 || a6; // object || enum is {} -var rg8 = a8 || a6; // array || enum is {} +var rg7 = a7 || a6; // object || enum is object | enum +var rg8 = a8 || a6; // array || enum is array | enum var rg9 = null || a6; // null || enum is E var rg10 = undefined || a6; // undefined || enum is E var rh1 = a1 || a7; // any || object is any -var rh2 = a2 || a7; // boolean || object is {} -var rh3 = a3 || a7; // number || object is {} -var rh4 = a4 || a7; // string || object is {} -var rh5 = a5 || a7; // void || object is {} -var rh6 = a6 || a7; // enum || object is {} +var rh2 = a2 || a7; // boolean || object is boolean | object +var rh3 = a3 || a7; // number || object is number | object +var rh4 = a4 || a7; // string || object is string | object +var rh5 = a5 || a7; // void || object is void | object +var rh6 = a6 || a7; // enum || object is enum | object var rh7 = a7 || a7; // object || object is object -var rh8 = a8 || a7; // array || object is {} +var rh8 = a8 || a7; // array || object is array | object var rh9 = null || a7; // null || object is object var rh10 = undefined || a7; // undefined || object is object var ri1 = a1 || a8; // any || array is any -var ri2 = a2 || a8; // boolean || array is {} -var ri3 = a3 || a8; // number || array is {} -var ri4 = a4 || a8; // string || array is {} -var ri5 = a5 || a8; // void || array is {} -var ri6 = a6 || a8; // enum || array is {} -var ri7 = a7 || a8; // object || array is {} +var ri2 = a2 || a8; // boolean || array is boolean | array +var ri3 = a3 || a8; // number || array is number | array +var ri4 = a4 || a8; // string || array is string | array +var ri5 = a5 || a8; // void || array is void | array +var ri6 = a6 || a8; // enum || array is enum | array +var ri7 = a7 || a8; // object || array is object | array var ri8 = a8 || a8; // array || array is array var ri9 = null || a8; // null || array is array var ri10 = undefined || a8; // undefined || array is array From 24ebc750c007a3752d135940bebff54427d2b118 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 16:25:09 -0800 Subject: [PATCH 11/41] Tests for Conditional operator can generate union type --- ...nditionalOperatorConditionIsBooleanType.js | 14 +++++ ...tionalOperatorConditionIsBooleanType.types | 45 ++++++++++++++ ...onditionalOperatorConditionIsNumberType.js | 13 +++- ...itionalOperatorConditionIsNumberType.types | 42 +++++++++++++ ...onditionalOperatorConditionIsObjectType.js | 12 ++++ ...itionalOperatorConditionIsObjectType.types | 49 +++++++++++++++ .../conditionalOperatorConditoinIsAnyType.js | 17 +++++- ...onditionalOperatorConditoinIsAnyType.types | 59 +++++++++++++++++++ ...onditionalOperatorConditoinIsStringType.js | 15 ++++- ...itionalOperatorConditoinIsStringType.types | 48 +++++++++++++++ ...onalOperatorWithoutIdenticalBCT.errors.txt | 11 ++-- .../conditionalOperatorWithoutIdenticalBCT.js | 7 ++- ...nditionalOperatorConditionIsBooleanType.ts | 7 +++ ...onditionalOperatorConditionIsNumberType.ts | 6 ++ ...onditionalOperatorConditionIsObjectType.ts | 6 ++ .../conditionalOperatorConditoinIsAnyType.ts | 8 +++ ...onditionalOperatorConditoinIsStringType.ts | 7 +++ .../conditionalOperatorWithoutIdenticalBCT.ts | 4 +- 18 files changed, 361 insertions(+), 9 deletions(-) diff --git a/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.js b/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.js index ab9dca9023f..d9a8b2daa29 100644 --- a/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.js +++ b/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.js @@ -20,6 +20,7 @@ condBoolean ? exprBoolean1 : exprBoolean2; condBoolean ? exprNumber1 : exprNumber2; condBoolean ? exprString1 : exprString2; condBoolean ? exprIsObject1 : exprIsObject2; +condBoolean ? exprString1 : exprBoolean1; // union //Cond is a boolean type literal true ? exprAny1 : exprAny2; @@ -27,6 +28,7 @@ false ? exprBoolean1 : exprBoolean2; true ? exprNumber1 : exprNumber2; false ? exprString1 : exprString2; true ? exprIsObject1 : exprIsObject2; +true ? exprString1 : exprBoolean1; // union //Cond is a boolean type expression !true ? exprAny1 : exprAny2; @@ -34,6 +36,7 @@ typeof "123" == "string" ? exprBoolean1 : exprBoolean2; 2 > 1 ? exprNumber1 : exprNumber2; null === undefined ? exprString1 : exprString2; true || false ? exprIsObject1 : exprIsObject2; +null === undefined ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condBoolean ? exprAny1 : exprAny2; @@ -41,18 +44,22 @@ var resultIsBoolean1 = condBoolean ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condBoolean ? exprNumber1 : exprNumber2; var resultIsString1 = condBoolean ? exprString1 : exprString2; var resultIsObject1 = condBoolean ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condBoolean ? exprString1 : exprBoolean1; // union var resultIsAny2 = true ? exprAny1 : exprAny2; var resultIsBoolean2 = false ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = true ? exprNumber1 : exprNumber2; var resultIsString2 = false ? exprString1 : exprString2; var resultIsObject2 = true ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = true ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean3 = false ? exprString1 : exprBoolean1; // union var resultIsAny3 = !true ? exprAny1 : exprAny2; var resultIsBoolean3 = typeof "123" == "string" ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = 2 > 1 ? exprNumber1 : exprNumber2; var resultIsString3 = null === undefined ? exprString1 : exprString2; var resultIsObject3 = true || false ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean4 = typeof "123" === "string" ? exprString1 : exprBoolean1; // union //// [conditionalOperatorConditionIsBooleanType.js] @@ -74,31 +81,38 @@ condBoolean ? exprBoolean1 : exprBoolean2; condBoolean ? exprNumber1 : exprNumber2; condBoolean ? exprString1 : exprString2; condBoolean ? exprIsObject1 : exprIsObject2; +condBoolean ? exprString1 : exprBoolean1; // union //Cond is a boolean type literal true ? exprAny1 : exprAny2; false ? exprBoolean1 : exprBoolean2; true ? exprNumber1 : exprNumber2; false ? exprString1 : exprString2; true ? exprIsObject1 : exprIsObject2; +true ? exprString1 : exprBoolean1; // union //Cond is a boolean type expression !true ? exprAny1 : exprAny2; typeof "123" == "string" ? exprBoolean1 : exprBoolean2; 2 > 1 ? exprNumber1 : exprNumber2; null === undefined ? exprString1 : exprString2; true || false ? exprIsObject1 : exprIsObject2; +null === undefined ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condBoolean ? exprAny1 : exprAny2; var resultIsBoolean1 = condBoolean ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condBoolean ? exprNumber1 : exprNumber2; var resultIsString1 = condBoolean ? exprString1 : exprString2; var resultIsObject1 = condBoolean ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condBoolean ? exprString1 : exprBoolean1; // union var resultIsAny2 = true ? exprAny1 : exprAny2; var resultIsBoolean2 = false ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = true ? exprNumber1 : exprNumber2; var resultIsString2 = false ? exprString1 : exprString2; var resultIsObject2 = true ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = true ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean3 = false ? exprString1 : exprBoolean1; // union var resultIsAny3 = !true ? exprAny1 : exprAny2; var resultIsBoolean3 = typeof "123" == "string" ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = 2 > 1 ? exprNumber1 : exprNumber2; var resultIsString3 = null === undefined ? exprString1 : exprString2; var resultIsObject3 = true || false ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean4 = typeof "123" === "string" ? exprString1 : exprBoolean1; // union diff --git a/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types b/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types index b3ca65219cb..44fc9f5ed7b 100644 --- a/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types +++ b/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types @@ -66,6 +66,12 @@ condBoolean ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +condBoolean ? exprString1 : exprBoolean1; // union +>condBoolean ? exprString1 : exprBoolean1 : string | boolean +>condBoolean : boolean +>exprString1 : string +>exprBoolean1 : boolean + //Cond is a boolean type literal true ? exprAny1 : exprAny2; >true ? exprAny1 : exprAny2 : any @@ -92,6 +98,11 @@ true ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +true ? exprString1 : exprBoolean1; // union +>true ? exprString1 : exprBoolean1 : string | boolean +>exprString1 : string +>exprBoolean1 : boolean + //Cond is a boolean type expression !true ? exprAny1 : exprAny2; >!true ? exprAny1 : exprAny2 : any @@ -125,6 +136,13 @@ true || false ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +null === undefined ? exprString1 : exprBoolean1; // union +>null === undefined ? exprString1 : exprBoolean1 : string | boolean +>null === undefined : boolean +>undefined : undefined +>exprString1 : string +>exprBoolean1 : boolean + //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condBoolean ? exprAny1 : exprAny2; >resultIsAny1 : any @@ -161,6 +179,13 @@ var resultIsObject1 = condBoolean ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean1 = condBoolean ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean1 : string | boolean +>condBoolean ? exprString1 : exprBoolean1 : string | boolean +>condBoolean : boolean +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny2 = true ? exprAny1 : exprAny2; >resultIsAny2 : any >true ? exprAny1 : exprAny2 : any @@ -191,6 +216,18 @@ var resultIsObject2 = true ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean2 = true ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean2 : string | boolean +>true ? exprString1 : exprBoolean1 : string | boolean +>exprString1 : string +>exprBoolean1 : boolean + +var resultIsStringOrBoolean3 = false ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean3 : string | boolean +>false ? exprString1 : exprBoolean1 : string | boolean +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny3 = !true ? exprAny1 : exprAny2; >resultIsAny3 : any >!true ? exprAny1 : exprAny2 : any @@ -228,3 +265,11 @@ var resultIsObject3 = true || false ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean4 = typeof "123" === "string" ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean4 : string | boolean +>typeof "123" === "string" ? exprString1 : exprBoolean1 : string | boolean +>typeof "123" === "string" : boolean +>typeof "123" : string +>exprString1 : string +>exprBoolean1 : boolean + diff --git a/tests/baselines/reference/conditionalOperatorConditionIsNumberType.js b/tests/baselines/reference/conditionalOperatorConditionIsNumberType.js index 166841f0a89..46a04169e93 100644 --- a/tests/baselines/reference/conditionalOperatorConditionIsNumberType.js +++ b/tests/baselines/reference/conditionalOperatorConditionIsNumberType.js @@ -20,6 +20,7 @@ condNumber ? exprBoolean1 : exprBoolean2; condNumber ? exprNumber1 : exprNumber2; condNumber ? exprString1 : exprString2; condNumber ? exprIsObject1 : exprIsObject2; +condNumber ? exprString1 : exprBoolean1; // Union //Cond is a number type literal 1 ? exprAny1 : exprAny2; @@ -27,6 +28,7 @@ condNumber ? exprIsObject1 : exprIsObject2; 0.123456789 ? exprNumber1 : exprNumber2; - 10000000000000 ? exprString1 : exprString2; 1000000000000 ? exprIsObject1 : exprIsObject2; +10000 ? exprString1 : exprBoolean1; // Union //Cond is a number type expression function foo() { return 1 }; @@ -37,6 +39,7 @@ var array = [1, 2, 3]; "string".length ? exprNumber1 : exprNumber2; foo() ? exprString1 : exprString2; foo() / array[1] ? exprIsObject1 : exprIsObject2; +foo() ? exprString1 : exprBoolean1; // Union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condNumber ? exprAny1 : exprAny2; @@ -44,19 +47,21 @@ var resultIsBoolean1 = condNumber ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condNumber ? exprNumber1 : exprNumber2; var resultIsString1 = condNumber ? exprString1 : exprString2; var resultIsObject1 = condNumber ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condNumber ? exprString1 : exprBoolean1; // Union var resultIsAny2 = 1 ? exprAny1 : exprAny2; var resultIsBoolean2 = 0 ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = 0.123456789 ? exprNumber1 : exprNumber2; var resultIsString2 = - 10000000000000 ? exprString1 : exprString2; var resultIsObject2 = 1000000000000 ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = 10000 ? exprString1 : exprBoolean1; // Union var resultIsAny3 = 1 * 0 ? exprAny1 : exprAny2; var resultIsBoolean3 = 1 + 1 ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = "string".length ? exprNumber1 : exprNumber2; var resultIsString3 = foo() ? exprString1 : exprString2; var resultIsObject3 = foo() / array[1] ? exprIsObject1 : exprIsObject2; - +var resultIsStringOrBoolean3 = foo() / array[1] ? exprString1 : exprBoolean1; // Union //// [conditionalOperatorConditionIsNumberType.js] //Cond ? Expr1 : Expr2, Cond is of number type, Expr1 and Expr2 have the same type @@ -77,12 +82,14 @@ condNumber ? exprBoolean1 : exprBoolean2; condNumber ? exprNumber1 : exprNumber2; condNumber ? exprString1 : exprString2; condNumber ? exprIsObject1 : exprIsObject2; +condNumber ? exprString1 : exprBoolean1; // Union //Cond is a number type literal 1 ? exprAny1 : exprAny2; 0 ? exprBoolean1 : exprBoolean2; 0.123456789 ? exprNumber1 : exprNumber2; -10000000000000 ? exprString1 : exprString2; 1000000000000 ? exprIsObject1 : exprIsObject2; +10000 ? exprString1 : exprBoolean1; // Union //Cond is a number type expression function foo() { return 1; @@ -94,19 +101,23 @@ var array = [1, 2, 3]; "string".length ? exprNumber1 : exprNumber2; foo() ? exprString1 : exprString2; foo() / array[1] ? exprIsObject1 : exprIsObject2; +foo() ? exprString1 : exprBoolean1; // Union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condNumber ? exprAny1 : exprAny2; var resultIsBoolean1 = condNumber ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condNumber ? exprNumber1 : exprNumber2; var resultIsString1 = condNumber ? exprString1 : exprString2; var resultIsObject1 = condNumber ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condNumber ? exprString1 : exprBoolean1; // Union var resultIsAny2 = 1 ? exprAny1 : exprAny2; var resultIsBoolean2 = 0 ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = 0.123456789 ? exprNumber1 : exprNumber2; var resultIsString2 = -10000000000000 ? exprString1 : exprString2; var resultIsObject2 = 1000000000000 ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = 10000 ? exprString1 : exprBoolean1; // Union var resultIsAny3 = 1 * 0 ? exprAny1 : exprAny2; var resultIsBoolean3 = 1 + 1 ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = "string".length ? exprNumber1 : exprNumber2; var resultIsString3 = foo() ? exprString1 : exprString2; var resultIsObject3 = foo() / array[1] ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean3 = foo() / array[1] ? exprString1 : exprBoolean1; // Union diff --git a/tests/baselines/reference/conditionalOperatorConditionIsNumberType.types b/tests/baselines/reference/conditionalOperatorConditionIsNumberType.types index 3396885509a..99a81081d6b 100644 --- a/tests/baselines/reference/conditionalOperatorConditionIsNumberType.types +++ b/tests/baselines/reference/conditionalOperatorConditionIsNumberType.types @@ -66,6 +66,12 @@ condNumber ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +condNumber ? exprString1 : exprBoolean1; // Union +>condNumber ? exprString1 : exprBoolean1 : string | boolean +>condNumber : number +>exprString1 : string +>exprBoolean1 : boolean + //Cond is a number type literal 1 ? exprAny1 : exprAny2; >1 ? exprAny1 : exprAny2 : any @@ -93,6 +99,11 @@ condNumber ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +10000 ? exprString1 : exprBoolean1; // Union +>10000 ? exprString1 : exprBoolean1 : string | boolean +>exprString1 : string +>exprBoolean1 : boolean + //Cond is a number type expression function foo() { return 1 }; >foo : () => number @@ -137,6 +148,13 @@ foo() / array[1] ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +foo() ? exprString1 : exprBoolean1; // Union +>foo() ? exprString1 : exprBoolean1 : string | boolean +>foo() : number +>foo : () => number +>exprString1 : string +>exprBoolean1 : boolean + //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condNumber ? exprAny1 : exprAny2; >resultIsAny1 : any @@ -173,6 +191,13 @@ var resultIsObject1 = condNumber ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean1 = condNumber ? exprString1 : exprBoolean1; // Union +>resultIsStringOrBoolean1 : string | boolean +>condNumber ? exprString1 : exprBoolean1 : string | boolean +>condNumber : number +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny2 = 1 ? exprAny1 : exprAny2; >resultIsAny2 : any >1 ? exprAny1 : exprAny2 : any @@ -204,6 +229,12 @@ var resultIsObject2 = 1000000000000 ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean2 = 10000 ? exprString1 : exprBoolean1; // Union +>resultIsStringOrBoolean2 : string | boolean +>10000 ? exprString1 : exprBoolean1 : string | boolean +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny3 = 1 * 0 ? exprAny1 : exprAny2; >resultIsAny3 : any >1 * 0 ? exprAny1 : exprAny2 : any @@ -245,3 +276,14 @@ var resultIsObject3 = foo() / array[1] ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean3 = foo() / array[1] ? exprString1 : exprBoolean1; // Union +>resultIsStringOrBoolean3 : string | boolean +>foo() / array[1] ? exprString1 : exprBoolean1 : string | boolean +>foo() / array[1] : number +>foo() : number +>foo : () => number +>array[1] : number +>array : number[] +>exprString1 : string +>exprBoolean1 : boolean + diff --git a/tests/baselines/reference/conditionalOperatorConditionIsObjectType.js b/tests/baselines/reference/conditionalOperatorConditionIsObjectType.js index 3f98398d94d..b628c21bd14 100644 --- a/tests/baselines/reference/conditionalOperatorConditionIsObjectType.js +++ b/tests/baselines/reference/conditionalOperatorConditionIsObjectType.js @@ -23,6 +23,7 @@ condObject ? exprBoolean1 : exprBoolean2; condObject ? exprNumber1 : exprNumber2; condObject ? exprString1 : exprString2; condObject ? exprIsObject1 : exprIsObject2; +condObject ? exprString1 : exprBoolean1; // union //Cond is an object type literal ((a: string) => a.length) ? exprAny1 : exprAny2; @@ -30,6 +31,7 @@ condObject ? exprIsObject1 : exprIsObject2; ({}) ? exprNumber1 : exprNumber2; ({ a: 1, b: "s" }) ? exprString1 : exprString2; ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; +({ a: 1, b: "s" }) ? exprString1: exprBoolean1; // union //Cond is an object type expression foo() ? exprAny1 : exprAny2; @@ -37,6 +39,7 @@ new Date() ? exprBoolean1 : exprBoolean2; new C() ? exprNumber1 : exprNumber2; C.doIt() ? exprString1 : exprString2; condObject.valueOf() ? exprIsObject1 : exprIsObject2; +new Date() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condObject ? exprAny1 : exprAny2; @@ -44,18 +47,21 @@ var resultIsBoolean1 = condObject ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condObject ? exprNumber1 : exprNumber2; var resultIsString1 = condObject ? exprString1 : exprString2; var resultIsObject1 = condObject ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condObject ? exprString1 : exprBoolean1; // union var resultIsAny2 = ((a: string) => a.length) ? exprAny1 : exprAny2; var resultIsBoolean2 = ((a: string) => a.length) ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = ({}) ? exprNumber1 : exprNumber2; var resultIsString2 = ({ a: 1, b: "s" }) ? exprString1 : exprString2; var resultIsObject2 = ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = ({ a: 1, b: "s" }) ? exprString1 : exprBoolean1; // union var resultIsAny3 = foo() ? exprAny1 : exprAny2; var resultIsBoolean3 = new Date() ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = new C() ? exprNumber1 : exprNumber2; var resultIsString3 = C.doIt() ? exprString1 : exprString2; var resultIsObject3 = condObject.valueOf() ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean3 = C.doIt() ? exprString1 : exprBoolean1; // union //// [conditionalOperatorConditionIsObjectType.js] @@ -86,31 +92,37 @@ condObject ? exprBoolean1 : exprBoolean2; condObject ? exprNumber1 : exprNumber2; condObject ? exprString1 : exprString2; condObject ? exprIsObject1 : exprIsObject2; +condObject ? exprString1 : exprBoolean1; // union //Cond is an object type literal (function (a) { return a.length; }) ? exprAny1 : exprAny2; (function (a) { return a.length; }) ? exprBoolean1 : exprBoolean2; ({}) ? exprNumber1 : exprNumber2; ({ a: 1, b: "s" }) ? exprString1 : exprString2; ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; +({ a: 1, b: "s" }) ? exprString1 : exprBoolean1; // union //Cond is an object type expression foo() ? exprAny1 : exprAny2; new Date() ? exprBoolean1 : exprBoolean2; new C() ? exprNumber1 : exprNumber2; C.doIt() ? exprString1 : exprString2; condObject.valueOf() ? exprIsObject1 : exprIsObject2; +new Date() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condObject ? exprAny1 : exprAny2; var resultIsBoolean1 = condObject ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condObject ? exprNumber1 : exprNumber2; var resultIsString1 = condObject ? exprString1 : exprString2; var resultIsObject1 = condObject ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condObject ? exprString1 : exprBoolean1; // union var resultIsAny2 = (function (a) { return a.length; }) ? exprAny1 : exprAny2; var resultIsBoolean2 = (function (a) { return a.length; }) ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = ({}) ? exprNumber1 : exprNumber2; var resultIsString2 = ({ a: 1, b: "s" }) ? exprString1 : exprString2; var resultIsObject2 = ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = ({ a: 1, b: "s" }) ? exprString1 : exprBoolean1; // union var resultIsAny3 = foo() ? exprAny1 : exprAny2; var resultIsBoolean3 = new Date() ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = new C() ? exprNumber1 : exprNumber2; var resultIsString3 = C.doIt() ? exprString1 : exprString2; var resultIsObject3 = condObject.valueOf() ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean3 = C.doIt() ? exprString1 : exprBoolean1; // union diff --git a/tests/baselines/reference/conditionalOperatorConditionIsObjectType.types b/tests/baselines/reference/conditionalOperatorConditionIsObjectType.types index 36c15d64c54..171871c5dcf 100644 --- a/tests/baselines/reference/conditionalOperatorConditionIsObjectType.types +++ b/tests/baselines/reference/conditionalOperatorConditionIsObjectType.types @@ -74,6 +74,12 @@ condObject ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +condObject ? exprString1 : exprBoolean1; // union +>condObject ? exprString1 : exprBoolean1 : string | boolean +>condObject : Object +>exprString1 : string +>exprBoolean1 : boolean + //Cond is an object type literal ((a: string) => a.length) ? exprAny1 : exprAny2; >((a: string) => a.length) ? exprAny1 : exprAny2 : any @@ -122,6 +128,15 @@ condObject ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +({ a: 1, b: "s" }) ? exprString1: exprBoolean1; // union +>({ a: 1, b: "s" }) ? exprString1: exprBoolean1 : string | boolean +>({ a: 1, b: "s" }) : { a: number; b: string; } +>{ a: 1, b: "s" } : { a: number; b: string; } +>a : number +>b : string +>exprString1 : string +>exprBoolean1 : boolean + //Cond is an object type expression foo() ? exprAny1 : exprAny2; >foo() ? exprAny1 : exprAny2 : any @@ -162,6 +177,13 @@ condObject.valueOf() ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +new Date() ? exprString1 : exprBoolean1; // union +>new Date() ? exprString1 : exprBoolean1 : string | boolean +>new Date() : Date +>Date : { (): string; new (): Date; new (value: number): Date; new (value: string): Date; new (year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date; prototype: Date; parse(s: string): number; UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number; now(): number; } +>exprString1 : string +>exprBoolean1 : boolean + //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condObject ? exprAny1 : exprAny2; >resultIsAny1 : any @@ -198,6 +220,13 @@ var resultIsObject1 = condObject ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean1 = condObject ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean1 : string | boolean +>condObject ? exprString1 : exprBoolean1 : string | boolean +>condObject : Object +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny2 = ((a: string) => a.length) ? exprAny1 : exprAny2; >resultIsAny2 : any >((a: string) => a.length) ? exprAny1 : exprAny2 : any @@ -250,6 +279,16 @@ var resultIsObject2 = ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean2 = ({ a: 1, b: "s" }) ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean2 : string | boolean +>({ a: 1, b: "s" }) ? exprString1 : exprBoolean1 : string | boolean +>({ a: 1, b: "s" }) : { a: number; b: string; } +>{ a: 1, b: "s" } : { a: number; b: string; } +>a : number +>b : string +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny3 = foo() ? exprAny1 : exprAny2; >resultIsAny3 : any >foo() ? exprAny1 : exprAny2 : any @@ -294,3 +333,13 @@ var resultIsObject3 = condObject.valueOf() ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean3 = C.doIt() ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean3 : string | boolean +>C.doIt() ? exprString1 : exprBoolean1 : string | boolean +>C.doIt() : void +>C.doIt : () => void +>C : typeof C +>doIt : () => void +>exprString1 : string +>exprBoolean1 : boolean + diff --git a/tests/baselines/reference/conditionalOperatorConditoinIsAnyType.js b/tests/baselines/reference/conditionalOperatorConditoinIsAnyType.js index 5869023d17d..80cfaf97f26 100644 --- a/tests/baselines/reference/conditionalOperatorConditoinIsAnyType.js +++ b/tests/baselines/reference/conditionalOperatorConditoinIsAnyType.js @@ -21,6 +21,7 @@ condAny ? exprBoolean1 : exprBoolean2; condAny ? exprNumber1 : exprNumber2; condAny ? exprString1 : exprString2; condAny ? exprIsObject1 : exprIsObject2; +condAny ? exprString1 : exprBoolean1; // union //Cond is an any type literal null ? exprAny1 : exprAny2; @@ -28,6 +29,7 @@ null ? exprBoolean1 : exprBoolean2; undefined ? exprNumber1 : exprNumber2; [null, undefined] ? exprString1 : exprString2; [null, undefined] ? exprIsObject1 : exprIsObject2; +undefined ? exprString1 : exprBoolean1; // union //Cond is an any type expression x.doSomeThing() ? exprAny1 : exprAny2; @@ -35,6 +37,7 @@ x("x") ? exprBoolean1 : exprBoolean2; x(x) ? exprNumber1 : exprNumber2; x("x") ? exprString1 : exprString2; x.doSomeThing() ? exprIsObject1 : exprIsObject2; +x.doSomeThing() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condAny ? exprAny1 : exprAny2; @@ -42,19 +45,23 @@ var resultIsBoolean1 = condAny ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condAny ? exprNumber1 : exprNumber2; var resultIsString1 = condAny ? exprString1 : exprString2; var resultIsObject1 = condAny ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condAny ? exprString1 : exprBoolean1; // union var resultIsAny2 = null ? exprAny1 : exprAny2; var resultIsBoolean2 = null ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = undefined ? exprNumber1 : exprNumber2; var resultIsString2 = [null, undefined] ? exprString1 : exprString2; var resultIsObject2 = [null, undefined] ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = null ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean3 = undefined ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean4 = [null, undefined] ? exprString1 : exprBoolean1; // union var resultIsAny3 = x.doSomeThing() ? exprAny1 : exprAny2; var resultIsBoolean3 = x("x") ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = x(x) ? exprNumber1 : exprNumber2; var resultIsString3 = x("x") ? exprString1 : exprString2; var resultIsObject3 = x.doSomeThing() ? exprIsObject1 : exprIsObject2; - +var resultIsStringOrBoolean5 = x.doSomeThing() ? exprString1 : exprBoolean1; // union //// [conditionalOperatorConditoinIsAnyType.js] //Cond ? Expr1 : Expr2, Cond is of any type, Expr1 and Expr2 have the same type @@ -76,31 +83,39 @@ condAny ? exprBoolean1 : exprBoolean2; condAny ? exprNumber1 : exprNumber2; condAny ? exprString1 : exprString2; condAny ? exprIsObject1 : exprIsObject2; +condAny ? exprString1 : exprBoolean1; // union //Cond is an any type literal null ? exprAny1 : exprAny2; null ? exprBoolean1 : exprBoolean2; undefined ? exprNumber1 : exprNumber2; [null, undefined] ? exprString1 : exprString2; [null, undefined] ? exprIsObject1 : exprIsObject2; +undefined ? exprString1 : exprBoolean1; // union //Cond is an any type expression x.doSomeThing() ? exprAny1 : exprAny2; x("x") ? exprBoolean1 : exprBoolean2; x(x) ? exprNumber1 : exprNumber2; x("x") ? exprString1 : exprString2; x.doSomeThing() ? exprIsObject1 : exprIsObject2; +x.doSomeThing() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condAny ? exprAny1 : exprAny2; var resultIsBoolean1 = condAny ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condAny ? exprNumber1 : exprNumber2; var resultIsString1 = condAny ? exprString1 : exprString2; var resultIsObject1 = condAny ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condAny ? exprString1 : exprBoolean1; // union var resultIsAny2 = null ? exprAny1 : exprAny2; var resultIsBoolean2 = null ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = undefined ? exprNumber1 : exprNumber2; var resultIsString2 = [null, undefined] ? exprString1 : exprString2; var resultIsObject2 = [null, undefined] ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = null ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean3 = undefined ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean4 = [null, undefined] ? exprString1 : exprBoolean1; // union var resultIsAny3 = x.doSomeThing() ? exprAny1 : exprAny2; var resultIsBoolean3 = x("x") ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = x(x) ? exprNumber1 : exprNumber2; var resultIsString3 = x("x") ? exprString1 : exprString2; var resultIsObject3 = x.doSomeThing() ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean5 = x.doSomeThing() ? exprString1 : exprBoolean1; // union diff --git a/tests/baselines/reference/conditionalOperatorConditoinIsAnyType.types b/tests/baselines/reference/conditionalOperatorConditoinIsAnyType.types index 9f5fc9326bb..6542377795f 100644 --- a/tests/baselines/reference/conditionalOperatorConditoinIsAnyType.types +++ b/tests/baselines/reference/conditionalOperatorConditoinIsAnyType.types @@ -69,6 +69,12 @@ condAny ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +condAny ? exprString1 : exprBoolean1; // union +>condAny ? exprString1 : exprBoolean1 : string | boolean +>condAny : any +>exprString1 : string +>exprBoolean1 : boolean + //Cond is an any type literal null ? exprAny1 : exprAny2; >null ? exprAny1 : exprAny2 : any @@ -100,6 +106,12 @@ undefined ? exprNumber1 : exprNumber2; >exprIsObject1 : Object >exprIsObject2 : Object +undefined ? exprString1 : exprBoolean1; // union +>undefined ? exprString1 : exprBoolean1 : string | boolean +>undefined : undefined +>exprString1 : string +>exprBoolean1 : boolean + //Cond is an any type expression x.doSomeThing() ? exprAny1 : exprAny2; >x.doSomeThing() ? exprAny1 : exprAny2 : any @@ -141,6 +153,15 @@ x.doSomeThing() ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +x.doSomeThing() ? exprString1 : exprBoolean1; // union +>x.doSomeThing() ? exprString1 : exprBoolean1 : string | boolean +>x.doSomeThing() : any +>x.doSomeThing : any +>x : any +>doSomeThing : any +>exprString1 : string +>exprBoolean1 : boolean + //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condAny ? exprAny1 : exprAny2; >resultIsAny1 : any @@ -177,6 +198,13 @@ var resultIsObject1 = condAny ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean1 = condAny ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean1 : string | boolean +>condAny ? exprString1 : exprBoolean1 : string | boolean +>condAny : any +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny2 = null ? exprAny1 : exprAny2; >resultIsAny2 : any >null ? exprAny1 : exprAny2 : any @@ -212,6 +240,27 @@ var resultIsObject2 = [null, undefined] ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean2 = null ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean2 : string | boolean +>null ? exprString1 : exprBoolean1 : string | boolean +>exprString1 : string +>exprBoolean1 : boolean + +var resultIsStringOrBoolean3 = undefined ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean3 : string | boolean +>undefined ? exprString1 : exprBoolean1 : string | boolean +>undefined : undefined +>exprString1 : string +>exprBoolean1 : boolean + +var resultIsStringOrBoolean4 = [null, undefined] ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean4 : string | boolean +>[null, undefined] ? exprString1 : exprBoolean1 : string | boolean +>[null, undefined] : null[] +>undefined : undefined +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny3 = x.doSomeThing() ? exprAny1 : exprAny2; >resultIsAny3 : any >x.doSomeThing() ? exprAny1 : exprAny2 : any @@ -257,3 +306,13 @@ var resultIsObject3 = x.doSomeThing() ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean5 = x.doSomeThing() ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean5 : string | boolean +>x.doSomeThing() ? exprString1 : exprBoolean1 : string | boolean +>x.doSomeThing() : any +>x.doSomeThing : any +>x : any +>doSomeThing : any +>exprString1 : string +>exprBoolean1 : boolean + diff --git a/tests/baselines/reference/conditionalOperatorConditoinIsStringType.js b/tests/baselines/reference/conditionalOperatorConditoinIsStringType.js index 4bd67a40640..02c398e89e1 100644 --- a/tests/baselines/reference/conditionalOperatorConditoinIsStringType.js +++ b/tests/baselines/reference/conditionalOperatorConditoinIsStringType.js @@ -20,6 +20,7 @@ condString ? exprBoolean1 : exprBoolean2; condString ? exprNumber1 : exprNumber2; condString ? exprString1 : exprString2; condString ? exprIsObject1 : exprIsObject2; +condString ? exprString1 : exprBoolean1; // union //Cond is a string type literal "" ? exprAny1 : exprAny2; @@ -27,6 +28,7 @@ condString ? exprIsObject1 : exprIsObject2; 'c' ? exprNumber1 : exprNumber2; 'string' ? exprString1 : exprString2; " " ? exprIsObject1 : exprIsObject2; +"hello " ? exprString1 : exprBoolean1; // union //Cond is a string type expression function foo() { return "string" }; @@ -37,6 +39,7 @@ condString.toUpperCase ? exprBoolean1 : exprBoolean2; condString + "string" ? exprNumber1 : exprNumber2; foo() ? exprString1 : exprString2; array[1] ? exprIsObject1 : exprIsObject2; +foo() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condString ? exprAny1 : exprAny2; @@ -44,19 +47,22 @@ var resultIsBoolean1 = condString ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condString ? exprNumber1 : exprNumber2; var resultIsString1 = condString ? exprString1 : exprString2; var resultIsObject1 = condString ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condString ? exprString1 : exprBoolean1; // union var resultIsAny2 = "" ? exprAny1 : exprAny2; var resultIsBoolean2 = "string" ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = 'c' ? exprNumber1 : exprNumber2; var resultIsString2 = 'string' ? exprString1 : exprString2; var resultIsObject2 = " " ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = "hello" ? exprString1 : exprBoolean1; // union var resultIsAny3 = typeof condString ? exprAny1 : exprAny2; var resultIsBoolean3 = condString.toUpperCase ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = condString + "string" ? exprNumber1 : exprNumber2; var resultIsString3 = foo() ? exprString1 : exprString2; var resultIsObject3 = array[1] ? exprIsObject1 : exprIsObject2; - +var resultIsStringOrBoolean3 = typeof condString ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean4 = condString.toUpperCase ? exprString1 : exprBoolean1; // union //// [conditionalOperatorConditoinIsStringType.js] //Cond ? Expr1 : Expr2, Cond is of string type, Expr1 and Expr2 have the same type @@ -77,12 +83,14 @@ condString ? exprBoolean1 : exprBoolean2; condString ? exprNumber1 : exprNumber2; condString ? exprString1 : exprString2; condString ? exprIsObject1 : exprIsObject2; +condString ? exprString1 : exprBoolean1; // union //Cond is a string type literal "" ? exprAny1 : exprAny2; "string" ? exprBoolean1 : exprBoolean2; 'c' ? exprNumber1 : exprNumber2; 'string' ? exprString1 : exprString2; " " ? exprIsObject1 : exprIsObject2; +"hello " ? exprString1 : exprBoolean1; // union //Cond is a string type expression function foo() { return "string"; @@ -94,19 +102,24 @@ condString.toUpperCase ? exprBoolean1 : exprBoolean2; condString + "string" ? exprNumber1 : exprNumber2; foo() ? exprString1 : exprString2; array[1] ? exprIsObject1 : exprIsObject2; +foo() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condString ? exprAny1 : exprAny2; var resultIsBoolean1 = condString ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condString ? exprNumber1 : exprNumber2; var resultIsString1 = condString ? exprString1 : exprString2; var resultIsObject1 = condString ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condString ? exprString1 : exprBoolean1; // union var resultIsAny2 = "" ? exprAny1 : exprAny2; var resultIsBoolean2 = "string" ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = 'c' ? exprNumber1 : exprNumber2; var resultIsString2 = 'string' ? exprString1 : exprString2; var resultIsObject2 = " " ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = "hello" ? exprString1 : exprBoolean1; // union var resultIsAny3 = typeof condString ? exprAny1 : exprAny2; var resultIsBoolean3 = condString.toUpperCase ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = condString + "string" ? exprNumber1 : exprNumber2; var resultIsString3 = foo() ? exprString1 : exprString2; var resultIsObject3 = array[1] ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean3 = typeof condString ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean4 = condString.toUpperCase ? exprString1 : exprBoolean1; // union diff --git a/tests/baselines/reference/conditionalOperatorConditoinIsStringType.types b/tests/baselines/reference/conditionalOperatorConditoinIsStringType.types index 668e0fc437c..45a4db8d295 100644 --- a/tests/baselines/reference/conditionalOperatorConditoinIsStringType.types +++ b/tests/baselines/reference/conditionalOperatorConditoinIsStringType.types @@ -66,6 +66,12 @@ condString ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +condString ? exprString1 : exprBoolean1; // union +>condString ? exprString1 : exprBoolean1 : string | boolean +>condString : string +>exprString1 : string +>exprBoolean1 : boolean + //Cond is a string type literal "" ? exprAny1 : exprAny2; >"" ? exprAny1 : exprAny2 : any @@ -92,6 +98,11 @@ condString ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +"hello " ? exprString1 : exprBoolean1; // union +>"hello " ? exprString1 : exprBoolean1 : string | boolean +>exprString1 : string +>exprBoolean1 : boolean + //Cond is a string type expression function foo() { return "string" }; >foo : () => string @@ -136,6 +147,13 @@ array[1] ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +foo() ? exprString1 : exprBoolean1; // union +>foo() ? exprString1 : exprBoolean1 : string | boolean +>foo() : string +>foo : () => string +>exprString1 : string +>exprBoolean1 : boolean + //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condString ? exprAny1 : exprAny2; >resultIsAny1 : any @@ -172,6 +190,13 @@ var resultIsObject1 = condString ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean1 = condString ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean1 : string | boolean +>condString ? exprString1 : exprBoolean1 : string | boolean +>condString : string +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny2 = "" ? exprAny1 : exprAny2; >resultIsAny2 : any >"" ? exprAny1 : exprAny2 : any @@ -202,6 +227,12 @@ var resultIsObject2 = " " ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean2 = "hello" ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean2 : string | boolean +>"hello" ? exprString1 : exprBoolean1 : string | boolean +>exprString1 : string +>exprBoolean1 : boolean + var resultIsAny3 = typeof condString ? exprAny1 : exprAny2; >resultIsAny3 : any >typeof condString ? exprAny1 : exprAny2 : any @@ -243,3 +274,20 @@ var resultIsObject3 = array[1] ? exprIsObject1 : exprIsObject2; >exprIsObject1 : Object >exprIsObject2 : Object +var resultIsStringOrBoolean3 = typeof condString ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean3 : string | boolean +>typeof condString ? exprString1 : exprBoolean1 : string | boolean +>typeof condString : string +>condString : string +>exprString1 : string +>exprBoolean1 : boolean + +var resultIsStringOrBoolean4 = condString.toUpperCase ? exprString1 : exprBoolean1; // union +>resultIsStringOrBoolean4 : string | boolean +>condString.toUpperCase ? exprString1 : exprBoolean1 : string | boolean +>condString.toUpperCase : () => string +>condString : string +>toUpperCase : () => string +>exprString1 : string +>exprBoolean1 : boolean + diff --git a/tests/baselines/reference/conditionalOperatorWithoutIdenticalBCT.errors.txt b/tests/baselines/reference/conditionalOperatorWithoutIdenticalBCT.errors.txt index 27c08308c33..e04411e8f69 100644 --- a/tests/baselines/reference/conditionalOperatorWithoutIdenticalBCT.errors.txt +++ b/tests/baselines/reference/conditionalOperatorWithoutIdenticalBCT.errors.txt @@ -4,13 +4,13 @@ tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithou tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts(16,5): error TS2323: Type 'A | B' is not assignable to type 'B'. Type 'A' is not assignable to type 'B'. Property 'propertyB' is missing in type 'A'. -tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts(18,5): error TS2323: Type '((m: X) => number) | ((n: X) => string)' is not assignable to type '(t: X) => number'. +tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts(19,5): error TS2323: Type '((m: X) => number) | ((n: X) => string)' is not assignable to type '(t: X) => number'. Type '(n: X) => string' is not assignable to type '(t: X) => number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts(19,5): error TS2323: Type '((m: X) => number) | ((n: X) => string)' is not assignable to type '(t: X) => string'. +tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts(20,5): error TS2323: Type '((m: X) => number) | ((n: X) => string)' is not assignable to type '(t: X) => string'. Type '(m: X) => number' is not assignable to type '(t: X) => string'. Type 'number' is not assignable to type 'string'. -tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts(20,5): error TS2323: Type '((m: X) => number) | ((n: X) => string)' is not assignable to type '(t: X) => boolean'. +tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts(21,5): error TS2323: Type '((m: X) => number) | ((n: X) => string)' is not assignable to type '(t: X) => boolean'. Type '(m: X) => number' is not assignable to type '(t: X) => boolean'. Type 'number' is not assignable to type 'boolean'. @@ -40,6 +40,7 @@ tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithou !!! error TS2323: Type 'A | B' is not assignable to type 'B'. !!! error TS2323: Type 'A' is not assignable to type 'B'. !!! error TS2323: Property 'propertyB' is missing in type 'A'. + var result31: A | B = true ? a : b; var result4: (t: X) => number = true ? (m) => m.propertyX1 : (n) => n.propertyX2; ~~~~~~~ @@ -55,4 +56,6 @@ tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithou ~~~~~~~ !!! error TS2323: Type '((m: X) => number) | ((n: X) => string)' is not assignable to type '(t: X) => boolean'. !!! error TS2323: Type '(m: X) => number' is not assignable to type '(t: X) => boolean'. -!!! error TS2323: Type 'number' is not assignable to type 'boolean'. \ No newline at end of file +!!! error TS2323: Type 'number' is not assignable to type 'boolean'. + var result61: (t: X) => number| string = true ? (m) => m.propertyX1 : (n) => n.propertyX2; + \ No newline at end of file diff --git a/tests/baselines/reference/conditionalOperatorWithoutIdenticalBCT.js b/tests/baselines/reference/conditionalOperatorWithoutIdenticalBCT.js index b6376dd781f..83262ed1301 100644 --- a/tests/baselines/reference/conditionalOperatorWithoutIdenticalBCT.js +++ b/tests/baselines/reference/conditionalOperatorWithoutIdenticalBCT.js @@ -15,10 +15,13 @@ var result1 = true ? a : b; //Be contextually typed and and bct is not identical, results in errors that union type is not assignable to target var result2: A = true ? a : b; var result3: B = true ? a : b; +var result31: A | B = true ? a : b; var result4: (t: X) => number = true ? (m) => m.propertyX1 : (n) => n.propertyX2; var result5: (t: X) => string = true ? (m) => m.propertyX1 : (n) => n.propertyX2; -var result6: (t: X) => boolean = true ? (m) => m.propertyX1 : (n) => n.propertyX2; +var result6: (t: X) => boolean = true ? (m) => m.propertyX1 : (n) => n.propertyX2; +var result61: (t: X) => number| string = true ? (m) => m.propertyX1 : (n) => n.propertyX2; + //// [conditionalOperatorWithoutIdenticalBCT.js] var __extends = this.__extends || function (d, b) { @@ -59,6 +62,8 @@ var result1 = true ? a : b; //Be contextually typed and and bct is not identical, results in errors that union type is not assignable to target var result2 = true ? a : b; var result3 = true ? a : b; +var result31 = true ? a : b; var result4 = true ? function (m) { return m.propertyX1; } : function (n) { return n.propertyX2; }; var result5 = true ? function (m) { return m.propertyX1; } : function (n) { return n.propertyX2; }; var result6 = true ? function (m) { return m.propertyX1; } : function (n) { return n.propertyX2; }; +var result61 = true ? function (m) { return m.propertyX1; } : function (n) { return n.propertyX2; }; diff --git a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsBooleanType.ts b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsBooleanType.ts index 80c2a8e8ec8..67b609e03e9 100644 --- a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsBooleanType.ts +++ b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsBooleanType.ts @@ -19,6 +19,7 @@ condBoolean ? exprBoolean1 : exprBoolean2; condBoolean ? exprNumber1 : exprNumber2; condBoolean ? exprString1 : exprString2; condBoolean ? exprIsObject1 : exprIsObject2; +condBoolean ? exprString1 : exprBoolean1; // union //Cond is a boolean type literal true ? exprAny1 : exprAny2; @@ -26,6 +27,7 @@ false ? exprBoolean1 : exprBoolean2; true ? exprNumber1 : exprNumber2; false ? exprString1 : exprString2; true ? exprIsObject1 : exprIsObject2; +true ? exprString1 : exprBoolean1; // union //Cond is a boolean type expression !true ? exprAny1 : exprAny2; @@ -33,6 +35,7 @@ typeof "123" == "string" ? exprBoolean1 : exprBoolean2; 2 > 1 ? exprNumber1 : exprNumber2; null === undefined ? exprString1 : exprString2; true || false ? exprIsObject1 : exprIsObject2; +null === undefined ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condBoolean ? exprAny1 : exprAny2; @@ -40,15 +43,19 @@ var resultIsBoolean1 = condBoolean ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condBoolean ? exprNumber1 : exprNumber2; var resultIsString1 = condBoolean ? exprString1 : exprString2; var resultIsObject1 = condBoolean ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condBoolean ? exprString1 : exprBoolean1; // union var resultIsAny2 = true ? exprAny1 : exprAny2; var resultIsBoolean2 = false ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = true ? exprNumber1 : exprNumber2; var resultIsString2 = false ? exprString1 : exprString2; var resultIsObject2 = true ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = true ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean3 = false ? exprString1 : exprBoolean1; // union var resultIsAny3 = !true ? exprAny1 : exprAny2; var resultIsBoolean3 = typeof "123" == "string" ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = 2 > 1 ? exprNumber1 : exprNumber2; var resultIsString3 = null === undefined ? exprString1 : exprString2; var resultIsObject3 = true || false ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean4 = typeof "123" === "string" ? exprString1 : exprBoolean1; // union diff --git a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsNumberType.ts b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsNumberType.ts index 5ec1beb9342..2e2c39ef316 100644 --- a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsNumberType.ts +++ b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsNumberType.ts @@ -19,6 +19,7 @@ condNumber ? exprBoolean1 : exprBoolean2; condNumber ? exprNumber1 : exprNumber2; condNumber ? exprString1 : exprString2; condNumber ? exprIsObject1 : exprIsObject2; +condNumber ? exprString1 : exprBoolean1; // Union //Cond is a number type literal 1 ? exprAny1 : exprAny2; @@ -26,6 +27,7 @@ condNumber ? exprIsObject1 : exprIsObject2; 0.123456789 ? exprNumber1 : exprNumber2; - 10000000000000 ? exprString1 : exprString2; 1000000000000 ? exprIsObject1 : exprIsObject2; +10000 ? exprString1 : exprBoolean1; // Union //Cond is a number type expression function foo() { return 1 }; @@ -36,6 +38,7 @@ var array = [1, 2, 3]; "string".length ? exprNumber1 : exprNumber2; foo() ? exprString1 : exprString2; foo() / array[1] ? exprIsObject1 : exprIsObject2; +foo() ? exprString1 : exprBoolean1; // Union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condNumber ? exprAny1 : exprAny2; @@ -43,15 +46,18 @@ var resultIsBoolean1 = condNumber ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condNumber ? exprNumber1 : exprNumber2; var resultIsString1 = condNumber ? exprString1 : exprString2; var resultIsObject1 = condNumber ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condNumber ? exprString1 : exprBoolean1; // Union var resultIsAny2 = 1 ? exprAny1 : exprAny2; var resultIsBoolean2 = 0 ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = 0.123456789 ? exprNumber1 : exprNumber2; var resultIsString2 = - 10000000000000 ? exprString1 : exprString2; var resultIsObject2 = 1000000000000 ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = 10000 ? exprString1 : exprBoolean1; // Union var resultIsAny3 = 1 * 0 ? exprAny1 : exprAny2; var resultIsBoolean3 = 1 + 1 ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = "string".length ? exprNumber1 : exprNumber2; var resultIsString3 = foo() ? exprString1 : exprString2; var resultIsObject3 = foo() / array[1] ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean3 = foo() / array[1] ? exprString1 : exprBoolean1; // Union \ No newline at end of file diff --git a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts index 5c8dcf0a13e..24b6970e12b 100644 --- a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts +++ b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts @@ -22,6 +22,7 @@ condObject ? exprBoolean1 : exprBoolean2; condObject ? exprNumber1 : exprNumber2; condObject ? exprString1 : exprString2; condObject ? exprIsObject1 : exprIsObject2; +condObject ? exprString1 : exprBoolean1; // union //Cond is an object type literal ((a: string) => a.length) ? exprAny1 : exprAny2; @@ -29,6 +30,7 @@ condObject ? exprIsObject1 : exprIsObject2; ({}) ? exprNumber1 : exprNumber2; ({ a: 1, b: "s" }) ? exprString1 : exprString2; ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; +({ a: 1, b: "s" }) ? exprString1: exprBoolean1; // union //Cond is an object type expression foo() ? exprAny1 : exprAny2; @@ -36,6 +38,7 @@ new Date() ? exprBoolean1 : exprBoolean2; new C() ? exprNumber1 : exprNumber2; C.doIt() ? exprString1 : exprString2; condObject.valueOf() ? exprIsObject1 : exprIsObject2; +new Date() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condObject ? exprAny1 : exprAny2; @@ -43,15 +46,18 @@ var resultIsBoolean1 = condObject ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condObject ? exprNumber1 : exprNumber2; var resultIsString1 = condObject ? exprString1 : exprString2; var resultIsObject1 = condObject ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condObject ? exprString1 : exprBoolean1; // union var resultIsAny2 = ((a: string) => a.length) ? exprAny1 : exprAny2; var resultIsBoolean2 = ((a: string) => a.length) ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = ({}) ? exprNumber1 : exprNumber2; var resultIsString2 = ({ a: 1, b: "s" }) ? exprString1 : exprString2; var resultIsObject2 = ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = ({ a: 1, b: "s" }) ? exprString1 : exprBoolean1; // union var resultIsAny3 = foo() ? exprAny1 : exprAny2; var resultIsBoolean3 = new Date() ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = new C() ? exprNumber1 : exprNumber2; var resultIsString3 = C.doIt() ? exprString1 : exprString2; var resultIsObject3 = condObject.valueOf() ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean3 = C.doIt() ? exprString1 : exprBoolean1; // union diff --git a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditoinIsAnyType.ts b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditoinIsAnyType.ts index 67ef99da141..3a03dfdacaa 100644 --- a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditoinIsAnyType.ts +++ b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditoinIsAnyType.ts @@ -20,6 +20,7 @@ condAny ? exprBoolean1 : exprBoolean2; condAny ? exprNumber1 : exprNumber2; condAny ? exprString1 : exprString2; condAny ? exprIsObject1 : exprIsObject2; +condAny ? exprString1 : exprBoolean1; // union //Cond is an any type literal null ? exprAny1 : exprAny2; @@ -27,6 +28,7 @@ null ? exprBoolean1 : exprBoolean2; undefined ? exprNumber1 : exprNumber2; [null, undefined] ? exprString1 : exprString2; [null, undefined] ? exprIsObject1 : exprIsObject2; +undefined ? exprString1 : exprBoolean1; // union //Cond is an any type expression x.doSomeThing() ? exprAny1 : exprAny2; @@ -34,6 +36,7 @@ x("x") ? exprBoolean1 : exprBoolean2; x(x) ? exprNumber1 : exprNumber2; x("x") ? exprString1 : exprString2; x.doSomeThing() ? exprIsObject1 : exprIsObject2; +x.doSomeThing() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condAny ? exprAny1 : exprAny2; @@ -41,15 +44,20 @@ var resultIsBoolean1 = condAny ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condAny ? exprNumber1 : exprNumber2; var resultIsString1 = condAny ? exprString1 : exprString2; var resultIsObject1 = condAny ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condAny ? exprString1 : exprBoolean1; // union var resultIsAny2 = null ? exprAny1 : exprAny2; var resultIsBoolean2 = null ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = undefined ? exprNumber1 : exprNumber2; var resultIsString2 = [null, undefined] ? exprString1 : exprString2; var resultIsObject2 = [null, undefined] ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = null ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean3 = undefined ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean4 = [null, undefined] ? exprString1 : exprBoolean1; // union var resultIsAny3 = x.doSomeThing() ? exprAny1 : exprAny2; var resultIsBoolean3 = x("x") ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = x(x) ? exprNumber1 : exprNumber2; var resultIsString3 = x("x") ? exprString1 : exprString2; var resultIsObject3 = x.doSomeThing() ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean5 = x.doSomeThing() ? exprString1 : exprBoolean1; // union \ No newline at end of file diff --git a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditoinIsStringType.ts b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditoinIsStringType.ts index 37fd9102922..e8f026d52e3 100644 --- a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditoinIsStringType.ts +++ b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditoinIsStringType.ts @@ -19,6 +19,7 @@ condString ? exprBoolean1 : exprBoolean2; condString ? exprNumber1 : exprNumber2; condString ? exprString1 : exprString2; condString ? exprIsObject1 : exprIsObject2; +condString ? exprString1 : exprBoolean1; // union //Cond is a string type literal "" ? exprAny1 : exprAny2; @@ -26,6 +27,7 @@ condString ? exprIsObject1 : exprIsObject2; 'c' ? exprNumber1 : exprNumber2; 'string' ? exprString1 : exprString2; " " ? exprIsObject1 : exprIsObject2; +"hello " ? exprString1 : exprBoolean1; // union //Cond is a string type expression function foo() { return "string" }; @@ -36,6 +38,7 @@ condString.toUpperCase ? exprBoolean1 : exprBoolean2; condString + "string" ? exprNumber1 : exprNumber2; foo() ? exprString1 : exprString2; array[1] ? exprIsObject1 : exprIsObject2; +foo() ? exprString1 : exprBoolean1; // union //Results shoud be same as Expr1 and Expr2 var resultIsAny1 = condString ? exprAny1 : exprAny2; @@ -43,15 +46,19 @@ var resultIsBoolean1 = condString ? exprBoolean1 : exprBoolean2; var resultIsNumber1 = condString ? exprNumber1 : exprNumber2; var resultIsString1 = condString ? exprString1 : exprString2; var resultIsObject1 = condString ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean1 = condString ? exprString1 : exprBoolean1; // union var resultIsAny2 = "" ? exprAny1 : exprAny2; var resultIsBoolean2 = "string" ? exprBoolean1 : exprBoolean2; var resultIsNumber2 = 'c' ? exprNumber1 : exprNumber2; var resultIsString2 = 'string' ? exprString1 : exprString2; var resultIsObject2 = " " ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean2 = "hello" ? exprString1 : exprBoolean1; // union var resultIsAny3 = typeof condString ? exprAny1 : exprAny2; var resultIsBoolean3 = condString.toUpperCase ? exprBoolean1 : exprBoolean2; var resultIsNumber3 = condString + "string" ? exprNumber1 : exprNumber2; var resultIsString3 = foo() ? exprString1 : exprString2; var resultIsObject3 = array[1] ? exprIsObject1 : exprIsObject2; +var resultIsStringOrBoolean3 = typeof condString ? exprString1 : exprBoolean1; // union +var resultIsStringOrBoolean4 = condString.toUpperCase ? exprString1 : exprBoolean1; // union \ No newline at end of file diff --git a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts index feaa3c5a280..f529b4fb9a0 100644 --- a/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts +++ b/tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorWithoutIdenticalBCT.ts @@ -14,7 +14,9 @@ var result1 = true ? a : b; //Be contextually typed and and bct is not identical, results in errors that union type is not assignable to target var result2: A = true ? a : b; var result3: B = true ? a : b; +var result31: A | B = true ? a : b; var result4: (t: X) => number = true ? (m) => m.propertyX1 : (n) => n.propertyX2; var result5: (t: X) => string = true ? (m) => m.propertyX1 : (n) => n.propertyX2; -var result6: (t: X) => boolean = true ? (m) => m.propertyX1 : (n) => n.propertyX2; \ No newline at end of file +var result6: (t: X) => boolean = true ? (m) => m.propertyX1 : (n) => n.propertyX2; +var result61: (t: X) => number| string = true ? (m) => m.propertyX1 : (n) => n.propertyX2; From 16fc7a22e23775a52fa1d152f217bc54eab1907e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 16:42:04 -0800 Subject: [PATCH 12/41] Tests for union type literals A union type literal is written as a sequence of types separated by vertical bars. UnionType: PrimaryOrUnionType | PrimaryType A union typle literal references a union type. When function or constructor types are included in union types they must be enclosed in parentheses --- .../baselines/reference/unionTypeLiterals.js | 29 ++++++++++++++++ .../reference/unionTypeLiterals.types | 34 +++++++++++++++++++ .../typeLiterals/unionTypeLiterals.ts | 15 ++++++++ 3 files changed, 78 insertions(+) create mode 100644 tests/baselines/reference/unionTypeLiterals.js create mode 100644 tests/baselines/reference/unionTypeLiterals.types create mode 100644 tests/cases/conformance/types/specifyingTypes/typeLiterals/unionTypeLiterals.ts diff --git a/tests/baselines/reference/unionTypeLiterals.js b/tests/baselines/reference/unionTypeLiterals.js new file mode 100644 index 00000000000..3e23d47d152 --- /dev/null +++ b/tests/baselines/reference/unionTypeLiterals.js @@ -0,0 +1,29 @@ +//// [unionTypeLiterals.ts] +// basic valid forms of union literals + +var simpleUnion: string | number; +var unionOfUnion: string | number | boolean; + +var arrayOfUnions: (string | number)[]; +var arrayOfUnions: Array; + +var unionOfFunctionType: (() => string) | (() => number); +var unionOfFunctionType: { (): string } | { (): number }; +var unionOfFunctionType: () => string | number; + +var unionOfConstructorType: (new () => string) | (new () => number); +var unionOfConstructorType: { new (): string } | { new (): number }; +var unionOfConstructorType: new () => string | number; + +//// [unionTypeLiterals.js] +// basic valid forms of union literals +var simpleUnion; +var unionOfUnion; +var arrayOfUnions; +var arrayOfUnions; +var unionOfFunctionType; +var unionOfFunctionType; +var unionOfFunctionType; +var unionOfConstructorType; +var unionOfConstructorType; +var unionOfConstructorType; diff --git a/tests/baselines/reference/unionTypeLiterals.types b/tests/baselines/reference/unionTypeLiterals.types new file mode 100644 index 00000000000..90bc4649aa7 --- /dev/null +++ b/tests/baselines/reference/unionTypeLiterals.types @@ -0,0 +1,34 @@ +=== tests/cases/conformance/types/specifyingTypes/typeLiterals/unionTypeLiterals.ts === +// basic valid forms of union literals + +var simpleUnion: string | number; +>simpleUnion : string | number + +var unionOfUnion: string | number | boolean; +>unionOfUnion : string | number | boolean + +var arrayOfUnions: (string | number)[]; +>arrayOfUnions : (string | number)[] + +var arrayOfUnions: Array; +>arrayOfUnions : (string | number)[] +>Array : T[] + +var unionOfFunctionType: (() => string) | (() => number); +>unionOfFunctionType : (() => string) | (() => number) + +var unionOfFunctionType: { (): string } | { (): number }; +>unionOfFunctionType : (() => string) | (() => number) + +var unionOfFunctionType: () => string | number; +>unionOfFunctionType : (() => string) | (() => number) + +var unionOfConstructorType: (new () => string) | (new () => number); +>unionOfConstructorType : (new () => string) | (new () => number) + +var unionOfConstructorType: { new (): string } | { new (): number }; +>unionOfConstructorType : (new () => string) | (new () => number) + +var unionOfConstructorType: new () => string | number; +>unionOfConstructorType : (new () => string) | (new () => number) + diff --git a/tests/cases/conformance/types/specifyingTypes/typeLiterals/unionTypeLiterals.ts b/tests/cases/conformance/types/specifyingTypes/typeLiterals/unionTypeLiterals.ts new file mode 100644 index 00000000000..7d52182beb3 --- /dev/null +++ b/tests/cases/conformance/types/specifyingTypes/typeLiterals/unionTypeLiterals.ts @@ -0,0 +1,15 @@ +// basic valid forms of union literals + +var simpleUnion: string | number; +var unionOfUnion: string | number | boolean; + +var arrayOfUnions: (string | number)[]; +var arrayOfUnions: Array; + +var unionOfFunctionType: (() => string) | (() => number); +var unionOfFunctionType: { (): string } | { (): number }; +var unionOfFunctionType: () => string | number; + +var unionOfConstructorType: (new () => string) | (new () => number); +var unionOfConstructorType: { new (): string } | { new (): number }; +var unionOfConstructorType: new () => string | number; \ No newline at end of file From 1ca9273f49753e864b3a20095feef66d369f1f3d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 3 Nov 2014 16:54:00 -0800 Subject: [PATCH 13/41] Identity of union type --- .../reference/unionTypeIdentity.errors.txt | 20 +++++++++++++++++++ .../baselines/reference/unionTypeIdentity.js | 19 ++++++++++++++++++ .../unionTypeIdentity.ts | 8 ++++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/baselines/reference/unionTypeIdentity.errors.txt create mode 100644 tests/baselines/reference/unionTypeIdentity.js create mode 100644 tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/unionTypeIdentity.ts diff --git a/tests/baselines/reference/unionTypeIdentity.errors.txt b/tests/baselines/reference/unionTypeIdentity.errors.txt new file mode 100644 index 00000000000..77d25bd78d1 --- /dev/null +++ b/tests/baselines/reference/unionTypeIdentity.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/unionTypeIdentity.ts(6,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'strOrNum' must be of type 'string | boolean', but here has type 'string'. +tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/unionTypeIdentity.ts(7,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'strOrNum' must be of type 'string | boolean', but here has type 'boolean'. +tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/unionTypeIdentity.ts(8,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'strOrNum' must be of type 'string | boolean', but here has type 'number'. + + +==== tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/unionTypeIdentity.ts (3 errors) ==== + // Two types are considered identical when + // they are union types with identical sets of constituent types, or + var strOrNum: string | boolean; + var strOrNum: boolean | string; + var strOrNum: boolean | string | boolean; + var strOrNum: string; // error + ~~~~~~~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'strOrNum' must be of type 'string | boolean', but here has type 'string'. + var strOrNum: boolean; // error + ~~~~~~~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'strOrNum' must be of type 'string | boolean', but here has type 'boolean'. + var strOrNum: number; // error + ~~~~~~~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'strOrNum' must be of type 'string | boolean', but here has type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/unionTypeIdentity.js b/tests/baselines/reference/unionTypeIdentity.js new file mode 100644 index 00000000000..82cad827979 --- /dev/null +++ b/tests/baselines/reference/unionTypeIdentity.js @@ -0,0 +1,19 @@ +//// [unionTypeIdentity.ts] +// Two types are considered identical when +// they are union types with identical sets of constituent types, or +var strOrNum: string | boolean; +var strOrNum: boolean | string; +var strOrNum: boolean | string | boolean; +var strOrNum: string; // error +var strOrNum: boolean; // error +var strOrNum: number; // error + +//// [unionTypeIdentity.js] +// Two types are considered identical when +// they are union types with identical sets of constituent types, or +var strOrNum; +var strOrNum; +var strOrNum; +var strOrNum; // error +var strOrNum; // error +var strOrNum; // error diff --git a/tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/unionTypeIdentity.ts b/tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/unionTypeIdentity.ts new file mode 100644 index 00000000000..79100f476bc --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/unionTypeIdentity.ts @@ -0,0 +1,8 @@ +// Two types are considered identical when +// they are union types with identical sets of constituent types, or +var strOrNum: string | boolean; +var strOrNum: boolean | string; +var strOrNum: boolean | string | boolean; +var strOrNum: string; // error +var strOrNum: boolean; // error +var strOrNum: number; // error \ No newline at end of file From 40af15c8ffc0bc805aff2f6ebf8a7a596013ecb7 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 4 Nov 2014 15:58:44 -0800 Subject: [PATCH 14/41] Array literal produces union type if the it is not contextually typed --- .../reference/unionTypeFromArrayLiteral.js | 79 +++++++++++++++++ .../reference/unionTypeFromArrayLiteral.types | 87 +++++++++++++++++++ .../types/union/unionTypeFromArrayLiteral.ts | 23 +++++ 3 files changed, 189 insertions(+) create mode 100644 tests/baselines/reference/unionTypeFromArrayLiteral.js create mode 100644 tests/baselines/reference/unionTypeFromArrayLiteral.types create mode 100644 tests/cases/conformance/types/union/unionTypeFromArrayLiteral.ts diff --git a/tests/baselines/reference/unionTypeFromArrayLiteral.js b/tests/baselines/reference/unionTypeFromArrayLiteral.js new file mode 100644 index 00000000000..e0410a65229 --- /dev/null +++ b/tests/baselines/reference/unionTypeFromArrayLiteral.js @@ -0,0 +1,79 @@ +//// [unionTypeFromArrayLiteral.ts] +// The resulting type an array literal expression is determined as follows: +// If the array literal is empty, the resulting type is an array type with the element type Undefined. +// Otherwise, if the array literal is contextually typed by a type that has a property with the numeric name ‘0’, the resulting type is a tuple type constructed from the types of the element expressions. +// Otherwise, the resulting type is an array type with an element type that is the union of the types of the element expressions. + +var arr1 = [1, 2]; // number[] +var arr2 = ["hello", true]; // (string | number)[] +var arr3Tuple: [number, string] = [3, "three"]; // [number, string] +var arr4Tuple: [number, string] = [3, "three", "hello"]; // [number, string, string] +var arrEmpty = []; +var arr5Tuple: { + 0: string; + 5: number; +} = ["hello", true, false, " hello", true, 10, "any"]; // Tuple +class C { foo() { } } +class D { foo2() { } } +class E extends C { foo3() { } } +class F extends C { foo4() { } } +var c: C, d: D, e: E, f: F; +var arr6 = [c, d]; // (C | D)[] +var arr7 = [c, d, e]; // (C | D)[] +var arr8 = [c, e]; // C[] +var arr9 = [e, f]; // (E|F)[] + +//// [unionTypeFromArrayLiteral.js] +// The resulting type an array literal expression is determined as follows: +// If the array literal is empty, the resulting type is an array type with the element type Undefined. +// Otherwise, if the array literal is contextually typed by a type that has a property with the numeric name ‘0’, the resulting type is a tuple type constructed from the types of the element expressions. +// Otherwise, the resulting type is an array type with an element type that is the union of the types of the element expressions. +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var arr1 = [1, 2]; // number[] +var arr2 = ["hello", true]; // (string | number)[] +var arr3Tuple = [3, "three"]; // [number, string] +var arr4Tuple = [3, "three", "hello"]; // [number, string, string] +var arrEmpty = []; +var arr5Tuple = ["hello", true, false, " hello", true, 10, "any"]; // Tuple +var C = (function () { + function C() { + } + C.prototype.foo = function () { + }; + return C; +})(); +var D = (function () { + function D() { + } + D.prototype.foo2 = function () { + }; + return D; +})(); +var E = (function (_super) { + __extends(E, _super); + function E() { + _super.apply(this, arguments); + } + E.prototype.foo3 = function () { + }; + return E; +})(C); +var F = (function (_super) { + __extends(F, _super); + function F() { + _super.apply(this, arguments); + } + F.prototype.foo4 = function () { + }; + return F; +})(C); +var c, d, e, f; +var arr6 = [c, d]; // (C | D)[] +var arr7 = [c, d, e]; // (C | D)[] +var arr8 = [c, e]; // C[] +var arr9 = [e, f]; // (E|F)[] diff --git a/tests/baselines/reference/unionTypeFromArrayLiteral.types b/tests/baselines/reference/unionTypeFromArrayLiteral.types new file mode 100644 index 00000000000..7cb09b3ce6a --- /dev/null +++ b/tests/baselines/reference/unionTypeFromArrayLiteral.types @@ -0,0 +1,87 @@ +=== tests/cases/conformance/types/union/unionTypeFromArrayLiteral.ts === +// The resulting type an array literal expression is determined as follows: +// If the array literal is empty, the resulting type is an array type with the element type Undefined. +// Otherwise, if the array literal is contextually typed by a type that has a property with the numeric name ‘0’, the resulting type is a tuple type constructed from the types of the element expressions. +// Otherwise, the resulting type is an array type with an element type that is the union of the types of the element expressions. + +var arr1 = [1, 2]; // number[] +>arr1 : number[] +>[1, 2] : number[] + +var arr2 = ["hello", true]; // (string | number)[] +>arr2 : (string | boolean)[] +>["hello", true] : (string | boolean)[] + +var arr3Tuple: [number, string] = [3, "three"]; // [number, string] +>arr3Tuple : [number, string] +>[3, "three"] : [number, string] + +var arr4Tuple: [number, string] = [3, "three", "hello"]; // [number, string, string] +>arr4Tuple : [number, string] +>[3, "three", "hello"] : [number, string, string] + +var arrEmpty = []; +>arrEmpty : any[] +>[] : undefined[] + +var arr5Tuple: { +>arr5Tuple : { 0: string; 5: number; } + + 0: string; + 5: number; +} = ["hello", true, false, " hello", true, 10, "any"]; // Tuple +>["hello", true, false, " hello", true, 10, "any"] : [string, boolean, boolean, string, boolean, number, string] + +class C { foo() { } } +>C : C +>foo : () => void + +class D { foo2() { } } +>D : D +>foo2 : () => void + +class E extends C { foo3() { } } +>E : E +>C : C +>foo3 : () => void + +class F extends C { foo4() { } } +>F : F +>C : C +>foo4 : () => void + +var c: C, d: D, e: E, f: F; +>c : C +>C : C +>d : D +>D : D +>e : E +>E : E +>f : F +>F : F + +var arr6 = [c, d]; // (C | D)[] +>arr6 : (C | D)[] +>[c, d] : (C | D)[] +>c : C +>d : D + +var arr7 = [c, d, e]; // (C | D)[] +>arr7 : (C | D)[] +>[c, d, e] : (C | D)[] +>c : C +>d : D +>e : E + +var arr8 = [c, e]; // C[] +>arr8 : C[] +>[c, e] : C[] +>c : C +>e : E + +var arr9 = [e, f]; // (E|F)[] +>arr9 : (E | F)[] +>[e, f] : (E | F)[] +>e : E +>f : F + diff --git a/tests/cases/conformance/types/union/unionTypeFromArrayLiteral.ts b/tests/cases/conformance/types/union/unionTypeFromArrayLiteral.ts new file mode 100644 index 00000000000..c6b57584673 --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeFromArrayLiteral.ts @@ -0,0 +1,23 @@ +// The resulting type an array literal expression is determined as follows: +// If the array literal is empty, the resulting type is an array type with the element type Undefined. +// Otherwise, if the array literal is contextually typed by a type that has a property with the numeric name ‘0’, the resulting type is a tuple type constructed from the types of the element expressions. +// Otherwise, the resulting type is an array type with an element type that is the union of the types of the element expressions. + +var arr1 = [1, 2]; // number[] +var arr2 = ["hello", true]; // (string | number)[] +var arr3Tuple: [number, string] = [3, "three"]; // [number, string] +var arr4Tuple: [number, string] = [3, "three", "hello"]; // [number, string, string] +var arrEmpty = []; +var arr5Tuple: { + 0: string; + 5: number; +} = ["hello", true, false, " hello", true, 10, "any"]; // Tuple +class C { foo() { } } +class D { foo2() { } } +class E extends C { foo3() { } } +class F extends C { foo4() { } } +var c: C, d: D, e: E, f: F; +var arr6 = [c, d]; // (C | D)[] +var arr7 = [c, d, e]; // (C | D)[] +var arr8 = [c, e]; // C[] +var arr9 = [e, f]; // (E|F)[] \ No newline at end of file From 9d31631fd716faf7e4ea6b6e60d8cdbaa451618b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 4 Nov 2014 16:40:56 -0800 Subject: [PATCH 15/41] Test cases of function infering return type of functions if f is a contextually typed function expression (section 4.9.3), the inferred return type is the union type (section 3.3.4) of the types of the return statement expressions in the function body, ignoring return statements with no expressions. Otherwise, the inferred return type is the first of the types of the return statement expressions in the function body that is a supertype (section 3.8.3) of each of the others, ignoring return statements with no expressions. A compile-time error occurs if no return statement expression has a type that is a supertype of each of the others. --- .../functionImplementationErrors.errors.txt | 67 ++++++++++- .../reference/functionImplementationErrors.js | 83 ++++++++++++++ .../reference/functionImplementations.js | 85 +++++++++++++- .../reference/functionImplementations.types | 105 ++++++++++++++++++ .../functions/functionImplementationErrors.ts | 29 +++++ .../functions/functionImplementations.ts | 37 +++++- 6 files changed, 400 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/functionImplementationErrors.errors.txt b/tests/baselines/reference/functionImplementationErrors.errors.txt index fbae17a609d..8ebd5aa272d 100644 --- a/tests/baselines/reference/functionImplementationErrors.errors.txt +++ b/tests/baselines/reference/functionImplementationErrors.errors.txt @@ -6,9 +6,15 @@ tests/cases/conformance/functions/functionImplementationErrors.ts(25,16): error tests/cases/conformance/functions/functionImplementationErrors.ts(30,17): error TS2373: Initializer of parameter 'n' cannot reference identifier 'm' declared after it. tests/cases/conformance/functions/functionImplementationErrors.ts(35,17): error TS2373: Initializer of parameter 'n' cannot reference identifier 'm' declared after it. tests/cases/conformance/functions/functionImplementationErrors.ts(40,28): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. +tests/cases/conformance/functions/functionImplementationErrors.ts(49,1): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(53,10): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(57,11): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(61,1): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(65,11): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/functions/functionImplementationErrors.ts(69,11): error TS2354: No best common type exists among return expressions. -==== tests/cases/conformance/functions/functionImplementationErrors.ts (8 errors) ==== +==== tests/cases/conformance/functions/functionImplementationErrors.ts (14 errors) ==== // FunctionExpression with no return type annotation with multiple return statements with unrelated types var f1 = function () { ~~~~~~~~~~~~~ @@ -83,4 +89,63 @@ tests/cases/conformance/functions/functionImplementationErrors.ts(40,28): error throw undefined; var x = 4; }; + + class Base { private x; } + class AnotherClass { private y; } + class Derived1 extends Base { private m; } + class Derived2 extends Base { private n; } + function f8() { + ~~~~~~~~~~~~~~~ + return new Derived1(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + return new Derived2(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + ~ +!!! error TS2354: No best common type exists among return expressions. + var f9 = function () { + ~~~~~~~~~~~~~ + return new Derived1(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + return new Derived2(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~ +!!! error TS2354: No best common type exists among return expressions. + var f10 = () => { + ~~~~~~~ + return new Derived1(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + return new Derived2(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~ +!!! error TS2354: No best common type exists among return expressions. + function f11() { + ~~~~~~~~~~~~~~~~ + return new Base(); + ~~~~~~~~~~~~~~~~~~~~~~ + return new AnotherClass(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + ~ +!!! error TS2354: No best common type exists among return expressions. + var f12 = function () { + ~~~~~~~~~~~~~ + return new Base(); + ~~~~~~~~~~~~~~~~~~~~~~ + return new AnotherClass(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~ +!!! error TS2354: No best common type exists among return expressions. + var f13 = () => { + ~~~~~~~ + return new Base(); + ~~~~~~~~~~~~~~~~~~~~~~ + return new AnotherClass(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~ +!!! error TS2354: No best common type exists among return expressions. \ No newline at end of file diff --git a/tests/baselines/reference/functionImplementationErrors.js b/tests/baselines/reference/functionImplementationErrors.js index 90e1997f396..5eaf9027335 100644 --- a/tests/baselines/reference/functionImplementationErrors.js +++ b/tests/baselines/reference/functionImplementationErrors.js @@ -42,9 +42,44 @@ undefined === function (): number { throw undefined; var x = 4; }; + +class Base { private x; } +class AnotherClass { private y; } +class Derived1 extends Base { private m; } +class Derived2 extends Base { private n; } +function f8() { + return new Derived1(); + return new Derived2(); +} +var f9 = function () { + return new Derived1(); + return new Derived2(); +}; +var f10 = () => { + return new Derived1(); + return new Derived2(); +}; +function f11() { + return new Base(); + return new AnotherClass(); +} +var f12 = function () { + return new Base(); + return new AnotherClass(); +}; +var f13 = () => { + return new Base(); + return new AnotherClass(); +}; //// [functionImplementationErrors.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; // FunctionExpression with no return type annotation with multiple return statements with unrelated types var f1 = function () { return ''; @@ -86,3 +121,51 @@ undefined === function () { throw undefined; var x = 4; }; +var Base = (function () { + function Base() { + } + return Base; +})(); +var AnotherClass = (function () { + function AnotherClass() { + } + return AnotherClass; +})(); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + return Derived1; +})(Base); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +})(Base); +function f8() { + return new Derived1(); + return new Derived2(); +} +var f9 = function () { + return new Derived1(); + return new Derived2(); +}; +var f10 = function () { + return new Derived1(); + return new Derived2(); +}; +function f11() { + return new Base(); + return new AnotherClass(); +} +var f12 = function () { + return new Base(); + return new AnotherClass(); +}; +var f13 = function () { + return new Base(); + return new AnotherClass(); +}; diff --git a/tests/baselines/reference/functionImplementations.js b/tests/baselines/reference/functionImplementations.js index 365ee1d7c0d..7c7b753a880 100644 --- a/tests/baselines/reference/functionImplementations.js +++ b/tests/baselines/reference/functionImplementations.js @@ -70,6 +70,10 @@ var n = function () { return 5; }(); +// Otherwise, the inferred return type is the first of the types of the return statement expressions +// in the function body that is a supertype of each of the others, +// ignoring return statements with no expressions. +// A compile - time error occurs if no return statement expression has a type that is a supertype of each of the others. // FunctionExpression with no return type annotation with multiple return statements with subtype relation between returns class Base { private m; } class Derived extends Base { private q; } @@ -120,9 +124,37 @@ function f6(): number { return; } - - - +class Derived2 extends Base { private r: string; } +class AnotherClass { private x } +// if f is a contextually typed function expression, the inferred return type is the union type +// of the types of the return statement expressions in the function body, +// ignoring return statements with no expressions. +var f7: (x: number) => string | number = x => { // should be (x: number) => number | string + if (x < 0) { return x; } + return x.toString(); +} +var f8: (x: number) => any = x => { // should be (x: number) => Base + return new Base(); + return new Derived2(); +} +var f9: (x: number) => any = x => { // should be (x: number) => Base + return new Base(); + return new Derived(); + return new Derived2(); +} +var f10: (x: number) => any = x => { // should be (x: number) => Derived | Derived1 + return new Derived(); + return new Derived2(); +} +var f11: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass + return new Base(); + return new AnotherClass(); +} +var f12: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass + return new Base(); + return; // should be ignored + return new AnotherClass(); +} //// [functionImplementations.js] var __extends = this.__extends || function (d, b) { @@ -192,6 +224,10 @@ var n = function () { return 3; return 5; }(); +// Otherwise, the inferred return type is the first of the types of the return statement expressions +// in the function body that is a supertype of each of the others, +// ignoring return statements with no expressions. +// A compile - time error occurs if no return statement expression has a type that is a supertype of each of the others. // FunctionExpression with no return type annotation with multiple return statements with subtype relation between returns var Base = (function () { function Base() { @@ -249,3 +285,46 @@ function opt3(n, m) { function f6() { return; } +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +})(Base); +var AnotherClass = (function () { + function AnotherClass() { + } + return AnotherClass; +})(); +// if f is a contextually typed function expression, the inferred return type is the union type +// of the types of the return statement expressions in the function body, +// ignoring return statements with no expressions. +var f7 = function (x) { + if (x < 0) { + return x; + } + return x.toString(); +}; +var f8 = function (x) { + return new Base(); + return new Derived2(); +}; +var f9 = function (x) { + return new Base(); + return new Derived(); + return new Derived2(); +}; +var f10 = function (x) { + return new Derived(); + return new Derived2(); +}; +var f11 = function (x) { + return new Base(); + return new AnotherClass(); +}; +var f12 = function (x) { + return new Base(); + return; // should be ignored + return new AnotherClass(); +}; diff --git a/tests/baselines/reference/functionImplementations.types b/tests/baselines/reference/functionImplementations.types index 29fe7c0e39c..04144e3a65b 100644 --- a/tests/baselines/reference/functionImplementations.types +++ b/tests/baselines/reference/functionImplementations.types @@ -168,6 +168,10 @@ var n = function () { return 5; }(); +// Otherwise, the inferred return type is the first of the types of the return statement expressions +// in the function body that is a supertype of each of the others, +// ignoring return statements with no expressions. +// A compile - time error occurs if no return statement expression has a type that is a supertype of each of the others. // FunctionExpression with no return type annotation with multiple return statements with subtype relation between returns class Base { private m; } >Base : Base @@ -292,6 +296,107 @@ function f6(): number { return; } +class Derived2 extends Base { private r: string; } +>Derived2 : Derived2 +>Base : Base +>r : string +class AnotherClass { private x } +>AnotherClass : AnotherClass +>x : any +// if f is a contextually typed function expression, the inferred return type is the union type +// of the types of the return statement expressions in the function body, +// ignoring return statements with no expressions. +var f7: (x: number) => string | number = x => { // should be (x: number) => number | string +>f7 : (x: number) => string | number +>x : number +>x => { // should be (x: number) => number | string if (x < 0) { return x; } return x.toString();} : (x: number) => string | number +>x : number + if (x < 0) { return x; } +>x < 0 : boolean +>x : number +>x : number + + return x.toString(); +>x.toString() : string +>x.toString : (radix?: number) => string +>x : number +>toString : (radix?: number) => string +} +var f8: (x: number) => any = x => { // should be (x: number) => Base +>f8 : (x: number) => any +>x : number +>x => { // should be (x: number) => Base return new Base(); return new Derived2();} : (x: number) => Base +>x : number + + return new Base(); +>new Base() : Base +>Base : typeof Base + + return new Derived2(); +>new Derived2() : Derived2 +>Derived2 : typeof Derived2 +} +var f9: (x: number) => any = x => { // should be (x: number) => Base +>f9 : (x: number) => any +>x : number +>x => { // should be (x: number) => Base return new Base(); return new Derived(); return new Derived2();} : (x: number) => Base +>x : number + + return new Base(); +>new Base() : Base +>Base : typeof Base + + return new Derived(); +>new Derived() : Derived +>Derived : typeof Derived + + return new Derived2(); +>new Derived2() : Derived2 +>Derived2 : typeof Derived2 +} +var f10: (x: number) => any = x => { // should be (x: number) => Derived | Derived1 +>f10 : (x: number) => any +>x : number +>x => { // should be (x: number) => Derived | Derived1 return new Derived(); return new Derived2();} : (x: number) => Derived | Derived2 +>x : number + + return new Derived(); +>new Derived() : Derived +>Derived : typeof Derived + + return new Derived2(); +>new Derived2() : Derived2 +>Derived2 : typeof Derived2 +} +var f11: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass +>f11 : (x: number) => any +>x : number +>x => { // should be (x: number) => Base | AnotherClass return new Base(); return new AnotherClass();} : (x: number) => Base | AnotherClass +>x : number + + return new Base(); +>new Base() : Base +>Base : typeof Base + + return new AnotherClass(); +>new AnotherClass() : AnotherClass +>AnotherClass : typeof AnotherClass +} +var f12: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass +>f12 : (x: number) => any +>x : number +>x => { // should be (x: number) => Base | AnotherClass return new Base(); return; // should be ignored return new AnotherClass();} : (x: number) => Base | AnotherClass +>x : number + + return new Base(); +>new Base() : Base +>Base : typeof Base + + return; // should be ignored + return new AnotherClass(); +>new AnotherClass() : AnotherClass +>AnotherClass : typeof AnotherClass +} diff --git a/tests/cases/conformance/functions/functionImplementationErrors.ts b/tests/cases/conformance/functions/functionImplementationErrors.ts index 6db4f6ed7e1..ddd3ba0a2c1 100644 --- a/tests/cases/conformance/functions/functionImplementationErrors.ts +++ b/tests/cases/conformance/functions/functionImplementationErrors.ts @@ -41,3 +41,32 @@ undefined === function (): number { throw undefined; var x = 4; }; + +class Base { private x; } +class AnotherClass { private y; } +class Derived1 extends Base { private m; } +class Derived2 extends Base { private n; } +function f8() { + return new Derived1(); + return new Derived2(); +} +var f9 = function () { + return new Derived1(); + return new Derived2(); +}; +var f10 = () => { + return new Derived1(); + return new Derived2(); +}; +function f11() { + return new Base(); + return new AnotherClass(); +} +var f12 = function () { + return new Base(); + return new AnotherClass(); +}; +var f13 = () => { + return new Base(); + return new AnotherClass(); +}; diff --git a/tests/cases/conformance/functions/functionImplementations.ts b/tests/cases/conformance/functions/functionImplementations.ts index d49b4780772..df36a0b4457 100644 --- a/tests/cases/conformance/functions/functionImplementations.ts +++ b/tests/cases/conformance/functions/functionImplementations.ts @@ -69,6 +69,10 @@ var n = function () { return 5; }(); +// Otherwise, the inferred return type is the first of the types of the return statement expressions +// in the function body that is a supertype of each of the others, +// ignoring return statements with no expressions. +// A compile - time error occurs if no return statement expression has a type that is a supertype of each of the others. // FunctionExpression with no return type annotation with multiple return statements with subtype relation between returns class Base { private m; } class Derived extends Base { private q; } @@ -119,5 +123,34 @@ function f6(): number { return; } - - +class Derived2 extends Base { private r: string; } +class AnotherClass { private x } +// if f is a contextually typed function expression, the inferred return type is the union type +// of the types of the return statement expressions in the function body, +// ignoring return statements with no expressions. +var f7: (x: number) => string | number = x => { // should be (x: number) => number | string + if (x < 0) { return x; } + return x.toString(); +} +var f8: (x: number) => any = x => { // should be (x: number) => Base + return new Base(); + return new Derived2(); +} +var f9: (x: number) => any = x => { // should be (x: number) => Base + return new Base(); + return new Derived(); + return new Derived2(); +} +var f10: (x: number) => any = x => { // should be (x: number) => Derived | Derived1 + return new Derived(); + return new Derived2(); +} +var f11: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass + return new Base(); + return new AnotherClass(); +} +var f12: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass + return new Base(); + return; // should be ignored + return new AnotherClass(); +} \ No newline at end of file From 460fc037e69145c52229ff9f1cd7c64e4fc75d05 Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 25 Nov 2014 12:12:55 -0800 Subject: [PATCH 16/41] Refactoring emitter for emit ES6 features natively --- src/compiler/checker.ts | 2 +- src/compiler/emitter.ts | 64 ++++++++++++++++++++++++----------------- src/compiler/parser.ts | 6 ++-- src/compiler/types.ts | 2 +- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5ee9fa4ab3e..321195e4fb5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8881,7 +8881,7 @@ module ts { // This is necessary as an identifier in short-hand property assignment can contains two meaning: // property name and property value. if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) { - return resolveEntityName(location, (location).name, SymbolFlags.Value); + return resolveEntityName(location, (location).name, SymbolFlags.Value); } return undefined; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 5cdf98aa63e..8a045bd1dc2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2197,33 +2197,28 @@ module ts { emitTrailingComments(node); } - function emitShortHandPropertyAssignment(node: ShortHandPropertyDeclaration) { - function emitAsNormalPropertyAssignment() { - emitLeadingComments(node); - // Emit identifier as an identifier - emit(node.name); - write(": "); - // Even though this is stored as identified because it is in short-hand property assignment, - // treated it as expression - emitExpressionIdentifier(node.name); - emitTrailingComments(node); - } + function emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node: ShorthandPropertyDeclaration) { + emitLeadingComments(node); + // Emit identifier as an identifier + emit(node.name); + write(": "); + // Even though this is stored as identified because it is in short-hand property assignment, + // treated it as expression + emitExpressionIdentifier(node.name); + emitTrailingComments(node); + } - if (compilerOptions.target < ScriptTarget.ES6) { - emitAsNormalPropertyAssignment(); + function emitShorthandPropertyAssignment(node: ShorthandPropertyDeclaration) { + // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment + var prefix = resolver.getExpressionNamePrefix(node.name); + if (prefix) { + emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node); } - else if (compilerOptions.target >= ScriptTarget.ES6) { - // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment - var prefix = resolver.getExpressionNamePrefix(node.name); - if (prefix) { - emitAsNormalPropertyAssignment(); - } - // If short-hand property has no prefix, emit it as short-hand. - else { - emitLeadingComments(node); - emit(node.name); - emitTrailingComments(node); - } + // If short-hand property has no prefix, emit it as short-hand. + else { + emitLeadingComments(node); + emit(node.name); + emitTrailingComments(node); } } @@ -3413,6 +3408,7 @@ module ts { return emitPinnedOrTripleSlashComments(node); } + // Check if node has SyntaxKind which can be emitted the same in both version of ES5 and ES6 switch (node.kind) { case SyntaxKind.Identifier: return emitIdentifier(node); @@ -3451,8 +3447,6 @@ module ts { return emitObjectLiteral(node); case SyntaxKind.PropertyAssignment: return emitPropertyAssignment(node); - case SyntaxKind.ShorthandPropertyAssignment: - return emitShortHandPropertyAssignment(node); case SyntaxKind.PropertyAccess: return emitPropertyAccess(node); case SyntaxKind.IndexedAccess: @@ -3539,6 +3533,22 @@ module ts { case SyntaxKind.SourceFile: return emitSourceFile(node); } + + // Emit node which needs to be emitted differently between ES5 and ES6 + if (compilerOptions.target < ScriptTarget.ES6) { + // Emit node down-leveling + switch (node.kind) { + case SyntaxKind.ShorthandPropertyAssignment: + return emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node); + } + } + else if (compilerOptions.target >= ScriptTarget.ES6) { + // Emit node natively in EcmaScript6 + switch (node.kind) { + case SyntaxKind.ShorthandPropertyAssignment: + return emitShorthandPropertyAssignment(node); + } + } } function hasDetachedComments(pos: number) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8d7bf9e4fe7..86b847d1aeb 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2764,7 +2764,7 @@ module ts { // Parse to check if it is short-hand property assignment or normal property assignment if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) { - node = createNode(SyntaxKind.ShorthandPropertyAssignment, nodePos); + node = createNode(SyntaxKind.ShorthandPropertyAssignment, nodePos); node.name = propertyName; } else { @@ -3968,7 +3968,7 @@ module ts { case SyntaxKind.ReturnStatement: return checkReturnStatement(node); case SyntaxKind.SetAccessor: return checkSetAccessor(node); case SyntaxKind.SourceFile: return checkSourceFile(node); - case SyntaxKind.ShorthandPropertyAssignment: return checkShorthandPropertyAssignment(node); + case SyntaxKind.ShorthandPropertyAssignment: return checkShorthandPropertyAssignment(node); case SyntaxKind.SwitchStatement: return checkSwitchStatement(node); case SyntaxKind.TaggedTemplateExpression: return checkTaggedTemplateExpression(node); case SyntaxKind.TupleType: return checkTupleType(node); @@ -4832,7 +4832,7 @@ module ts { return grammarErrorOnFirstToken(node, Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file); } - function checkShorthandPropertyAssignment(node: ShortHandPropertyDeclaration): boolean { + function checkShorthandPropertyAssignment(node: ShorthandPropertyDeclaration): boolean { return checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 83937c24ed9..3df983f595b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -360,7 +360,7 @@ module ts { initializer?: Expression; } - export interface ShortHandPropertyDeclaration extends Declaration { + export interface ShorthandPropertyDeclaration extends Declaration { name: Identifier; } From b55038314356215857247bb444b3d0b340c07a6a Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 25 Nov 2014 12:12:55 -0800 Subject: [PATCH 17/41] Refactoring emitter for emit ES6 features natively --- src/compiler/checker.ts | 2 +- src/compiler/emitter.ts | 64 ++++++++++++++++++++++++----------------- src/compiler/parser.ts | 6 ++-- src/compiler/types.ts | 2 +- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5ee9fa4ab3e..321195e4fb5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8881,7 +8881,7 @@ module ts { // This is necessary as an identifier in short-hand property assignment can contains two meaning: // property name and property value. if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) { - return resolveEntityName(location, (location).name, SymbolFlags.Value); + return resolveEntityName(location, (location).name, SymbolFlags.Value); } return undefined; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 5cdf98aa63e..6b5c8d1fe39 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2197,33 +2197,28 @@ module ts { emitTrailingComments(node); } - function emitShortHandPropertyAssignment(node: ShortHandPropertyDeclaration) { - function emitAsNormalPropertyAssignment() { - emitLeadingComments(node); - // Emit identifier as an identifier - emit(node.name); - write(": "); - // Even though this is stored as identified because it is in short-hand property assignment, - // treated it as expression - emitExpressionIdentifier(node.name); - emitTrailingComments(node); - } + function emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node: ShorthandPropertyDeclaration) { + emitLeadingComments(node); + // Emit identifier as an identifier + emit(node.name); + write(": "); + // Even though this is stored as identified because it is in short-hand property assignment, + // treated it as expression + emitExpressionIdentifier(node.name); + emitTrailingComments(node); + } - if (compilerOptions.target < ScriptTarget.ES6) { - emitAsNormalPropertyAssignment(); + function emitShorthandPropertyAssignment(node: ShorthandPropertyDeclaration) { + // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment + var prefix = resolver.getExpressionNamePrefix(node.name); + if (prefix) { + emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node); } - else if (compilerOptions.target >= ScriptTarget.ES6) { - // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment - var prefix = resolver.getExpressionNamePrefix(node.name); - if (prefix) { - emitAsNormalPropertyAssignment(); - } - // If short-hand property has no prefix, emit it as short-hand. - else { - emitLeadingComments(node); - emit(node.name); - emitTrailingComments(node); - } + // If short-hand property has no prefix, emit it as short-hand. + else { + emitLeadingComments(node); + emit(node.name); + emitTrailingComments(node); } } @@ -3413,6 +3408,7 @@ module ts { return emitPinnedOrTripleSlashComments(node); } + // Check if node has SyntaxKind which can be emitted regardless of the ScriptTarget switch (node.kind) { case SyntaxKind.Identifier: return emitIdentifier(node); @@ -3451,8 +3447,6 @@ module ts { return emitObjectLiteral(node); case SyntaxKind.PropertyAssignment: return emitPropertyAssignment(node); - case SyntaxKind.ShorthandPropertyAssignment: - return emitShortHandPropertyAssignment(node); case SyntaxKind.PropertyAccess: return emitPropertyAccess(node); case SyntaxKind.IndexedAccess: @@ -3539,6 +3533,22 @@ module ts { case SyntaxKind.SourceFile: return emitSourceFile(node); } + + // Emit node which needs to be emitted differently depended on ScriptTarget + if (compilerOptions.target < ScriptTarget.ES6) { + // Emit node down-leveling + switch (node.kind) { + case SyntaxKind.ShorthandPropertyAssignment: + return emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node); + } + } + else if (compilerOptions.target >= ScriptTarget.ES6) { + // Emit node natively in EcmaScript6 + switch (node.kind) { + case SyntaxKind.ShorthandPropertyAssignment: + return emitShorthandPropertyAssignment(node); + } + } } function hasDetachedComments(pos: number) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8d7bf9e4fe7..86b847d1aeb 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2764,7 +2764,7 @@ module ts { // Parse to check if it is short-hand property assignment or normal property assignment if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) { - node = createNode(SyntaxKind.ShorthandPropertyAssignment, nodePos); + node = createNode(SyntaxKind.ShorthandPropertyAssignment, nodePos); node.name = propertyName; } else { @@ -3968,7 +3968,7 @@ module ts { case SyntaxKind.ReturnStatement: return checkReturnStatement(node); case SyntaxKind.SetAccessor: return checkSetAccessor(node); case SyntaxKind.SourceFile: return checkSourceFile(node); - case SyntaxKind.ShorthandPropertyAssignment: return checkShorthandPropertyAssignment(node); + case SyntaxKind.ShorthandPropertyAssignment: return checkShorthandPropertyAssignment(node); case SyntaxKind.SwitchStatement: return checkSwitchStatement(node); case SyntaxKind.TaggedTemplateExpression: return checkTaggedTemplateExpression(node); case SyntaxKind.TupleType: return checkTupleType(node); @@ -4832,7 +4832,7 @@ module ts { return grammarErrorOnFirstToken(node, Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file); } - function checkShorthandPropertyAssignment(node: ShortHandPropertyDeclaration): boolean { + function checkShorthandPropertyAssignment(node: ShorthandPropertyDeclaration): boolean { return checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 83937c24ed9..3df983f595b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -360,7 +360,7 @@ module ts { initializer?: Expression; } - export interface ShortHandPropertyDeclaration extends Declaration { + export interface ShorthandPropertyDeclaration extends Declaration { name: Identifier; } From 7ba032be3dd5a0d4ad078ad3d6a068ef4951f171 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 1 Dec 2014 15:32:52 -0800 Subject: [PATCH 18/41] Emit services as an external module. --- Jakefile | 37 ++++++++++++++++++++++++++----------- src/services/shims.ts | 6 ++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/Jakefile b/Jakefile index ba82e9c3f43..9ecc126b06d 100644 --- a/Jakefile +++ b/Jakefile @@ -1,6 +1,7 @@ // This file contains the build logic for the public repo var fs = require("fs"); +var os = require("os"); var path = require("path"); var child_process = require("child_process"); @@ -145,7 +146,7 @@ var compilerFilename = "tsc.js"; * @param useBuiltCompiler: true to use the built compiler, false to use the LKG * @param noOutFile: true to compile without using --out */ -function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations) { +function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, callback) { file(outFile, prereqs, function() { var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory; var options = "-removeComments --module commonjs -noImplicitAny "; @@ -177,6 +178,11 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOu prependFile(prefixes[i], outFile); } } + + if (callback) { + callback(); + } + complete(); }); ex.addListener("error", function() { @@ -221,7 +227,7 @@ compileFile(processDiagnosticMessagesJs, [processDiagnosticMessagesTs], [processDiagnosticMessagesTs], [], - false); + /*useBuiltCompiler*/ false); // The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], function () { @@ -241,7 +247,6 @@ file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], ex.run(); }, {async: true}) - desc("Generates a diagnostic file in TypeScript based on an input JSON file"); task("generate-diagnostics", [diagnosticInfoMapTs]) @@ -252,13 +257,24 @@ compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(co var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js"); var servicesDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts"); -compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].concat(servicesSources), [copyright], /*useBuiltCompiler:*/ true, /*noOutFile:*/ false, /*generateDeclarations:*/ true); + +compileFile(servicesFile, + servicesSources, + [builtLocalDirectory, copyright].concat(servicesSources), + [copyright], + /*useBuiltCompiler*/ true, + /*noOutFile*/ false, + /*generateDeclarations*/ true, + /*callback*/ fixDeclarationFile); + +function fixDeclarationFile() { + fs.appendFileSync(servicesDefinitionsFile, os.EOL + "export = ts;") +} // Local target to build the compiler and services desc("Builds the full compiler and services"); task("local", ["generate-diagnostics", "lib", tscFile, servicesFile]); - // Local target to build the compiler and services desc("Sets release mode flag"); task("release", function() { @@ -275,7 +291,6 @@ task("clean", function() { jake.rmRf(builtDirectory); }); - // Generate Markdown spec var word2mdJs = path.join(scriptsDirectory, "word2md.js"); var word2mdTs = path.join(scriptsDirectory, "word2md.ts"); @@ -289,7 +304,7 @@ compileFile(word2mdJs, [word2mdTs], [word2mdTs], [], - false); + /*useBuiltCompiler*/ false); // The generated spec.md; built for the 'generate-spec' task file(specMd, [word2mdJs, specWord], function () { @@ -438,7 +453,7 @@ task("generate-code-coverage", ["tests", builtLocalDirectory], function () { // Browser tests var nodeServerOutFile = 'tests/webTestServer.js' var nodeServerInFile = 'tests/webTestServer.ts' -compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], true, true); +compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, /*noOutFile*/ true); desc("Runs browserify on run.js to produce a file suitable for running tests in the browser"); task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() { @@ -513,7 +528,7 @@ task("baseline-accept-rwc", function() { // Webhost var webhostPath = "tests/webhost/webtsc.ts"; var webhostJsPath = "tests/webhost/webtsc.js"; -compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryTargets), [], true); +compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryTargets), [], /*useBuiltCompiler*/true); desc("Builds the tsc web host"); task("webhost", [webhostJsPath], function() { @@ -523,7 +538,7 @@ task("webhost", [webhostJsPath], function() { // Perf compiler var perftscPath = "tests/perftsc.ts"; var perftscJsPath = "built/local/perftsc.js"; -compileFile(perftscJsPath, [perftscPath], [tscFile, perftscPath, "tests/perfsys.ts"].concat(libraryTargets), [], true); +compileFile(perftscJsPath, [perftscPath], [tscFile, perftscPath, "tests/perfsys.ts"].concat(libraryTargets), [], /*useBuiltCompiler*/ true); desc("Builds augmented version of the compiler for perf tests"); task("perftsc", [perftscJsPath]); @@ -547,7 +562,7 @@ file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function() { var instrumenterPath = harnessDirectory + 'instrumenter.ts'; var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js'; -compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath], [], true); +compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath], [], /*useBuiltCompiler*/ true); desc("Builds an instrumented tsc.js"); task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function() { diff --git a/src/services/shims.ts b/src/services/shims.ts index 49603fd4a2e..9428e8c534f 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -920,3 +920,9 @@ module TypeScript.Services { export var TypeScriptServicesFactory = ts.TypeScriptServicesFactory; } +module ts { + declare var module: any; + if (typeof module !== "undefined" && module.exports) { + module.exports = ts; + } +} \ No newline at end of file From 55be5300044c709cf6712fc9ef5dc34453cb803d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 1 Dec 2014 15:52:34 -0800 Subject: [PATCH 19/41] Get rid of emitted empty module. --- src/services/shims.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/services/shims.ts b/src/services/shims.ts index 9428e8c534f..64759fffc9f 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -912,6 +912,11 @@ module ts { throw new Error("Invalid operation"); } } + + declare var module: any; + if (typeof module !== "undefined" && module.exports) { + module.exports = ts; + } } @@ -919,10 +924,3 @@ module ts { module TypeScript.Services { export var TypeScriptServicesFactory = ts.TypeScriptServicesFactory; } - -module ts { - declare var module: any; - if (typeof module !== "undefined" && module.exports) { - module.exports = ts; - } -} \ No newline at end of file From f8a4fb0a15959bb0bfa1e9617402173e76dc4329 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 19:19:50 -0800 Subject: [PATCH 20/41] Put semantically relevant tokens in the tree. --- src/compiler/checker.ts | 14 +++++++------- src/compiler/emitter.ts | 2 +- src/compiler/parser.ts | 19 ++++++++++--------- src/compiler/types.ts | 2 +- src/services/breakpoints.ts | 2 +- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a663b038844..2f765e556cb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1437,7 +1437,7 @@ module ts { } function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) { - if (getDeclarationFlagsFromSymbol(p) & NodeFlags.Rest) { + if (hasDotDotDotToken(p.valueDeclaration)) { writePunctuation(writer, SyntaxKind.DotDotDotToken); } appendSymbolNameOnly(p, writer); @@ -1711,7 +1711,7 @@ module ts { } // Rest parameters default to type any[], other parameters default to type any - var type = declaration.flags & NodeFlags.Rest ? createArrayType(anyType) : anyType; + var type = hasDotDotDotToken(declaration) ? createArrayType(anyType) : anyType; checkImplicitAny(type); return type; @@ -1733,9 +1733,9 @@ module ts { var diagnostic = Diagnostics.Member_0_implicitly_has_an_1_type; break; case SyntaxKind.Parameter: - var diagnostic = declaration.flags & NodeFlags.Rest ? - Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : - Diagnostics.Parameter_0_implicitly_has_an_1_type; + var diagnostic = hasDotDotDotToken(declaration) + ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type + : Diagnostics.Parameter_0_implicitly_has_an_1_type; break; default: var diagnostic = Diagnostics.Variable_0_implicitly_has_an_1_type; @@ -2527,7 +2527,7 @@ module ts { hasStringLiterals = true; } if (minArgumentCount < 0) { - if (param.initializer || param.flags & (NodeFlags.QuestionMark | NodeFlags.Rest)) { + if (param.initializer || param.flags & NodeFlags.QuestionMark || param.dotDotDotToken) { minArgumentCount = i; } } @@ -6673,7 +6673,7 @@ module ts { !(parameterDeclaration.parent.kind === SyntaxKind.Constructor && (parameterDeclaration.parent).body)) { error(parameterDeclaration, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } - if (parameterDeclaration.flags & NodeFlags.Rest) { + if (parameterDeclaration.dotDotDotToken) { if (!isArrayType(getTypeOfSymbol(parameterDeclaration.symbol))) { error(parameterDeclaration, Diagnostics.A_rest_parameter_must_be_of_an_array_type); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fab0433890a..75454aa9807 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1252,7 +1252,7 @@ module ts { function emitParameterDeclaration(node: ParameterDeclaration) { increaseIndent(); emitJsDocComments(node); - if (node.flags & NodeFlags.Rest) { + if (node.dotDotDotToken) { write("..."); } writeTextOfNode(currentSourceFile, node.name); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 687eab878f3..733c28d267e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -608,8 +608,12 @@ module ts { return node.kind === SyntaxKind.ImportDeclaration && (node).moduleReference.kind !== SyntaxKind.ExternalModuleReference; } + export function hasDotDotDotToken(node: Node) { + return node && node.kind === SyntaxKind.Parameter && (node).dotDotDotToken !== undefined; + } + export function hasRestParameters(s: SignatureDeclaration): boolean { - return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0; + return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined; } export function isLiteralKind(kind: SyntaxKind): boolean { @@ -1812,11 +1816,8 @@ module ts { function parseParameter(): ParameterDeclaration { var node = createNode(SyntaxKind.Parameter); - var modifiers = parseModifiers(); - setModifiers(node, modifiers); - if (parseOptional(SyntaxKind.DotDotDotToken)) { - node.flags |= NodeFlags.Rest; - } + setModifiers(node, parseModifiers()); + node.dotDotDotToken = token === SyntaxKind.DotDotDotToken ? parseTokenNode() : undefined; // SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3 // [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt @@ -4803,7 +4804,7 @@ module ts { return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_exactly_one_parameter); } } - else if (parameter.flags & NodeFlags.Rest) { + else if (parameter.dotDotDotToken) { return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); } else if (parameter.flags & NodeFlags.Modifier) { @@ -5160,7 +5161,7 @@ module ts { for (var i = 0; i < parameterCount; i++) { var parameter = parameters[i]; - if (parameter.flags & NodeFlags.Rest) { + if (parameter.dotDotDotToken) { if (i !== (parameterCount - 1)) { return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } @@ -5298,7 +5299,7 @@ module ts { } else { var parameter = accessor.parameters[0]; - if (parameter.flags & NodeFlags.Rest) { + if (parameter.dotDotDotToken) { return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_rest_parameter); } else if (parameter.flags & NodeFlags.Modifier) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 277e2cce5ff..fba331fdd3c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -273,7 +273,6 @@ module ts { Export = 0x00000001, // Declarations Ambient = 0x00000002, // Declarations QuestionMark = 0x00000004, // Parameter/Property/Method - Rest = 0x00000008, // Parameter Public = 0x00000010, // Property/Method Private = 0x00000020, // Property/Method Protected = 0x00000040, // Property/Method @@ -369,6 +368,7 @@ module ts { } export interface ParameterDeclaration extends Declaration { + dotDotDotToken?: Node; name: Identifier; type?: TypeNode | StringLiteralExpression; initializer?: Expression; diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 6cf775487fa..eb9c88088aa 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -297,7 +297,7 @@ module ts.BreakpointResolver { function canHaveSpanInParameterDeclaration(parameter: ParameterDeclaration): boolean { // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier - return !!parameter.initializer || !!(parameter.flags & NodeFlags.Rest) || + return !!parameter.initializer || parameter.dotDotDotToken !== undefined || !!(parameter.flags & NodeFlags.Public) || !!(parameter.flags & NodeFlags.Private); } From 8ad4a0a5b873c4b7705e926595775bac0cce3ea9 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 20:45:29 -0800 Subject: [PATCH 21/41] Traverse into all nodes when walking the tree. --- src/compiler/parser.ts | 49 ++++++++++++++++++++++++++-------------- src/compiler/types.ts | 2 +- src/services/services.ts | 4 ++-- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 733c28d267e..8e6f0fda479 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -216,13 +216,16 @@ module ts { return child((node).name) || child((node).constraint); case SyntaxKind.Parameter: - return child((node).name) || + return children(node.modifiers) || + child((node).dotDotDotToken) || + child((node).name) || child((node).type) || child((node).initializer); case SyntaxKind.Property: case SyntaxKind.PropertyAssignment: case SyntaxKind.ShorthandPropertyAssignment: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).type) || child((node).initializer); case SyntaxKind.FunctionType: @@ -230,7 +233,8 @@ module ts { case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: - return children((node).typeParameters) || + return children(node.modifiers) || + children((node).typeParameters) || children((node).parameters) || child((node).type); case SyntaxKind.Method: @@ -240,7 +244,8 @@ module ts { case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: case SyntaxKind.ArrowFunction: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || children((node).typeParameters) || children((node).parameters) || child((node).type) || @@ -308,7 +313,8 @@ module ts { case SyntaxKind.SourceFile: return children((node).statements); case SyntaxKind.VariableStatement: - return children((node).declarations); + return children(node.modifiers) || + children((node).declarations); case SyntaxKind.ExpressionStatement: return child((node).expression); case SyntaxKind.IfStatement: @@ -360,36 +366,44 @@ module ts { return child((node).variable) || children((node).statements); case SyntaxKind.VariableDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).type) || child((node).initializer); case SyntaxKind.ClassDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || children((node).typeParameters) || children((node).heritageClauses) || children((node).members); case SyntaxKind.InterfaceDeclaration: - return child((node).name) || - children((node).typeParameters) || - children((node).heritageClauses) || + return children(node.modifiers) || + child((node).name) || + children((node).typeParameters) || + children((node).heritageClauses) || children((node).members); case SyntaxKind.TypeAliasDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).type); case SyntaxKind.EnumDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || children((node).members); case SyntaxKind.EnumMember: return child((node).name) || child((node).initializer); case SyntaxKind.ModuleDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).body); case SyntaxKind.ImportDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).moduleReference); case SyntaxKind.ExportAssignment: - return child((node).exportName); + return children(node.modifiers) || + child((node).exportName); case SyntaxKind.TemplateExpression: return child((node).head) || children((node).templateSpans); case SyntaxKind.TemplateSpan: @@ -3759,7 +3773,7 @@ module ts { var flags = 0; var modifiers: ModifiersArray; while (true) { - var modifierStart = scanner.getTokenPos(); + var modifierStart = scanner.getStartPos(); var modifierKind = token; if (!parseAnyContextualModifier()) { @@ -3768,12 +3782,14 @@ module ts { if (!modifiers) { modifiers = []; + modifiers.pos = modifierStart; } flags |= modifierToFlag(modifierKind); modifiers.push(finishNode(createNode(modifierKind, modifierStart))); } if (modifiers) { modifiers.flags = flags; + modifiers.end = scanner.getStartPos(); } return modifiers; } @@ -4049,7 +4065,6 @@ module ts { switch (token) { case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: - return parseVariableStatement(fullStart, modifiers); case SyntaxKind.ConstKeyword: return parseVariableStatement(fullStart, modifiers); case SyntaxKind.FunctionKeyword: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fba331fdd3c..8436399f74f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -317,7 +317,7 @@ module ts { hasTrailingComma?: boolean; } - export interface ModifiersArray extends Array { + export interface ModifiersArray extends NodeArray { flags: number; } diff --git a/src/services/services.ts b/src/services/services.ts index 8bbc03aad6f..7e9e84cd7af 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3836,8 +3836,8 @@ module ts { } forEach(nodes, node => { - if (node.flags & modifierFlag) { - forEach(node.getChildren(), child => pushKeywordIf(keywords, child, modifier)); + if (node.modifiers && node.flags & modifierFlag) { + forEach(node.modifiers, child => pushKeywordIf(keywords, child, modifier)); } }); From db89584a862bce6432ef7030ba79cf39732e2efe Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:03:41 -0800 Subject: [PATCH 22/41] Put semantically relevant tokens in the tree. --- src/compiler/checker.ts | 46 +++++--- src/compiler/emitter.ts | 6 +- src/compiler/parser.ts | 111 +++++++++--------- src/compiler/types.ts | 5 +- src/services/signatureHelp.ts | 2 +- .../accessorWithRestParam.errors.txt | 8 +- ...rowfunctionsOptionalArgsErrors1.errors.txt | 4 +- .../functionOverloadErrorsSyntax.errors.txt | 4 +- .../indexSignatureTypeCheck.errors.txt | 8 +- .../indexSignatureTypeCheck2.errors.txt | 8 +- .../reference/indexerAsOptional.errors.txt | 8 +- .../indexerSignatureWithRestParam.errors.txt | 8 +- .../parserIndexSignature1.errors.txt | 4 +- .../parserIndexSignature3.errors.txt | 4 +- ...rserMemberAccessorDeclaration17.errors.txt | 4 +- ...rserMemberAccessorDeclaration18.errors.txt | 4 +- .../reference/parserParameterList1.errors.txt | 4 +- .../parserParameterList11.errors.txt | 4 +- .../reference/parserParameterList9.errors.txt | 4 +- .../reference/restParamAsOptional.errors.txt | 4 +- .../reference/restParameterNotLast.errors.txt | 4 +- ...eterWithoutAnnotationIsAnyArray.errors.txt | 12 +- .../restParametersOfNonArrayTypes.errors.txt | 12 +- .../restParametersOfNonArrayTypes2.errors.txt | 24 ++-- ...ametersWithArrayTypeAnnotations.errors.txt | 24 ++-- 25 files changed, 175 insertions(+), 151 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2f765e556cb..9fca10b7341 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -756,7 +756,7 @@ module ts { // // x is an optional parameter, but it is a required property. return propertySymbol.valueDeclaration && - propertySymbol.valueDeclaration.flags & NodeFlags.QuestionMark && + hasQuestionToken(propertySymbol.valueDeclaration) && propertySymbol.valueDeclaration.kind !== SyntaxKind.Parameter; } @@ -1441,7 +1441,7 @@ module ts { writePunctuation(writer, SyntaxKind.DotDotDotToken); } appendSymbolNameOnly(p, writer); - if (p.valueDeclaration.flags & NodeFlags.QuestionMark || (p.valueDeclaration).initializer) { + if (hasQuestionToken(p.valueDeclaration) || (p.valueDeclaration).initializer) { writePunctuation(writer, SyntaxKind.QuestionToken); } writePunctuation(writer, SyntaxKind.ColonToken); @@ -2527,7 +2527,7 @@ module ts { hasStringLiterals = true; } if (minArgumentCount < 0) { - if (param.initializer || param.flags & NodeFlags.QuestionMark || param.dotDotDotToken) { + if (param.initializer || param.questionToken || param.dotDotDotToken) { minArgumentCount = i; } } @@ -7020,20 +7020,23 @@ module ts { return; } + function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration) { + // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration + // Error on all deviations from this canonical set of flags + // The caveat is that if some overloads are defined in lib.d.ts, we don't want to + // report the errors on those. To achieve this, we will say that the implementation is + // the canonical signature only if it is in the same container as the first overload + var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; + return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; + } + function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void { // Error if some overloads have a flag that is not shared by all overloads. To find the // deviations, we XOR someOverloadFlags with allOverloadFlags var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; if (someButNotAllOverloadFlags !== 0) { - // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration - // Error on all deviations from this canonical set of flags - // The caveat is that if some overloads are defined in lib.d.ts, we don't want to - // report the errors on those. To achieve this, we will say that the implementation is - // the canonical signature only if it is in the same container as the first overload - var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; - var canonicalFlags = implementationSharesContainerWithFirstOverload - ? getEffectiveDeclarationFlags(implementation, flagsToCheck) - : getEffectiveDeclarationFlags(overloads[0], flagsToCheck); + var canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck); + forEach(overloads, o => { var deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags; if (deviation & NodeFlags.Export) { @@ -7045,16 +7048,27 @@ module ts { else if (deviation & (NodeFlags.Private | NodeFlags.Protected)) { error(o.name, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); } - else if (deviation & NodeFlags.QuestionMark) { + }); + } + } + + function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { + if (someHaveQuestionToken !== allHaveQuestionToken) { + var canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation)); + forEach(overloads, o => { + var deviation = hasQuestionToken(o) !== canonicalHasQuestionToken; + if (deviation) { error(o.name, Diagnostics.Overload_signatures_must_all_be_optional_or_required); } }); } } - var flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected | NodeFlags.QuestionMark; + var flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected; var someNodeFlags: NodeFlags = 0; var allNodeFlags = flagsToCheck; + var someHaveQuestionToken = false; + var allHaveQuestionToken = true; var hasOverloads = false; var bodyDeclaration: FunctionLikeDeclaration; var lastSeenNonAmbientDeclaration: FunctionLikeDeclaration; @@ -7128,6 +7142,8 @@ module ts { var currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck); someNodeFlags |= currentNodeFlags; allNodeFlags &= currentNodeFlags; + someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken(node); + allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken(node); if (node.body && bodyDeclaration) { if (isConstructor) { @@ -7176,6 +7192,8 @@ module ts { if (hasOverloads) { checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags); + checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken); + if (bodyDeclaration) { var signatures = getSignaturesOfSymbol(symbol); var bodySignature = getSignatureFromDeclaration(bodyDeclaration); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 75454aa9807..ff52209ba69 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -943,7 +943,7 @@ module ts { if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) { writeTextOfNode(currentSourceFile, node.name); // If optional property emit ? - if (node.kind === SyntaxKind.Property && (node.flags & NodeFlags.QuestionMark)) { + if (node.kind === SyntaxKind.Property && hasQuestionToken(node)) { write("?"); } if (node.kind === SyntaxKind.Property && node.parent.kind === SyntaxKind.TypeLiteral) { @@ -1124,7 +1124,7 @@ module ts { } else { writeTextOfNode(currentSourceFile, node.name); - if (node.flags & NodeFlags.QuestionMark) { + if (hasQuestionToken(node)) { write("?"); } } @@ -1256,7 +1256,7 @@ module ts { write("..."); } writeTextOfNode(currentSourceFile, node.name); - if (node.initializer || (node.flags & NodeFlags.QuestionMark)) { + if (node.initializer || hasQuestionToken(node)) { write("?"); } decreaseIndent(); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8e6f0fda479..97b973eb8d0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -219,6 +219,7 @@ module ts { return children(node.modifiers) || child((node).dotDotDotToken) || child((node).name) || + child((node).questionToken) || child((node).type) || child((node).initializer); case SyntaxKind.Property: @@ -226,6 +227,7 @@ module ts { case SyntaxKind.ShorthandPropertyAssignment: return children(node.modifiers) || child((node).name) || + child((node).questionToken) || child((node).type) || child((node).initializer); case SyntaxKind.FunctionType: @@ -246,6 +248,7 @@ module ts { case SyntaxKind.ArrowFunction: return children(node.modifiers) || child((node).name) || + child((node).questionToken) || children((node).typeParameters) || children((node).parameters) || child((node).type) || @@ -626,6 +629,23 @@ module ts { return node && node.kind === SyntaxKind.Parameter && (node).dotDotDotToken !== undefined; } + export function hasQuestionToken(node: Node) { + if (node) { + switch (node.kind) { + case SyntaxKind.Parameter: + return (node).questionToken !== undefined; + case SyntaxKind.Method: + return (node).questionToken !== undefined; + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.Property: + return (node).questionToken !== undefined; + } + } + + return false; + } + export function hasRestParameters(s: SignatureDeclaration): boolean { return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined; } @@ -1853,9 +1873,7 @@ module ts { nextToken(); } - if (parseOptional(SyntaxKind.QuestionToken)) { - node.flags |= NodeFlags.QuestionMark; - } + node.questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; node.type = parseParameterType(); node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) @@ -2020,15 +2038,12 @@ module ts { function parsePropertyOrMethod(): Declaration { var fullStart = scanner.getStartPos(); var name = parsePropertyName(); - var flags = 0; - if (parseOptional(SyntaxKind.QuestionToken)) { - flags = NodeFlags.QuestionMark; - } + var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { var method = createNode(SyntaxKind.Method, fullStart); method.name = name; - method.flags = flags; + method.questionToken = questionToken; // Method signatues don't exist in expression contexts. So they have neither // [Yield] nor [GeneratorParameter] @@ -2040,7 +2055,7 @@ module ts { else { var property = createNode(SyntaxKind.Property, fullStart); property.name = name; - property.flags = flags; + property.questionToken = questionToken; property.type = parseTypeAnnotation(); parseSemicolon(); return finishNode(property); @@ -3125,28 +3140,24 @@ module ts { return finishNode(node); } - var flags: NodeFlags = 0; - // Disallowing of optional property assignments happens in the grammar checker. - if (token === SyntaxKind.QuestionToken) { - flags |= NodeFlags.QuestionMark; - nextToken(); - } + var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; // Parse to check if it is short-hand property assignment or normal property assignment if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) { - node = createNode(SyntaxKind.ShorthandPropertyAssignment, nodePos); - node.name = propertyName; + var shorthandDeclaration = createNode(SyntaxKind.ShorthandPropertyAssignment, nodePos); + shorthandDeclaration.name = propertyName; + shorthandDeclaration.questionToken = questionToken; + return finishNode(shorthandDeclaration); } else { - node = createNode(SyntaxKind.PropertyAssignment, nodePos); - node.name = propertyName; + var propertyDeclaration = createNode(SyntaxKind.PropertyAssignment, nodePos); + propertyDeclaration.name = propertyName; + propertyDeclaration.questionToken = questionToken; parseExpected(SyntaxKind.ColonToken); - (node).initializer = allowInAnd(parseAssignmentExpressionOrHigher); + propertyDeclaration.initializer = allowInAnd(parseAssignmentExpressionOrHigher); + return finishNode(propertyDeclaration); } - - node.flags = flags; - return finishNode(node); } function parseObjectLiteralMember(): Declaration { @@ -3671,23 +3682,18 @@ module ts { } function parsePropertyMemberDeclaration(fullStart: number, modifiers: ModifiersArray): ClassElement { - var flags = modifiers ? modifiers.flags : 0; var asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); var name = parsePropertyName(); - if (parseOptional(SyntaxKind.QuestionToken)) { - // Note: this is not legal as per the grammar. But we allow it in the parser and - // report an error in the grammar checker. - flags |= NodeFlags.QuestionMark; - } + // Note: this is not legal as per the grammar. But we allow it in the parser and + // report an error in the grammar checker. + var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; if (asteriskToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { var method = createNode(SyntaxKind.Method, fullStart); setModifiers(method, modifiers); - if (flags) { - method.flags = flags; - } method.asteriskToken = asteriskToken; method.name = name; + method.questionToken = questionToken; fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, method); method.body = parseFunctionBlockOrSemicolon(!!asteriskToken); return finishNode(method); @@ -3695,10 +3701,8 @@ module ts { else { var property = createNode(SyntaxKind.Property, fullStart); setModifiers(property, modifiers); - if (flags) { - property.flags = flags; - } property.name = name; + property.questionToken = questionToken; property.type = parseTypeAnnotation(); property.initializer = allowInAnd(() => parseInitializer(/*inParameter*/ false)); parseSemicolon(); @@ -4820,13 +4824,13 @@ module ts { } } else if (parameter.dotDotDotToken) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); } else if (parameter.flags & NodeFlags.Modifier) { return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier); } - else if (parameter.flags & NodeFlags.QuestionMark) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark); + else if (parameter.questionToken) { + return grammarErrorOnNode(parameter.questionToken, Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark); } else if (parameter.initializer) { return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_initializer); @@ -4878,7 +4882,7 @@ module ts { return true; } if (node.parent.kind === SyntaxKind.ClassDeclaration) { - if (checkForInvalidQuestionMark(node, Diagnostics.A_class_member_cannot_be_declared_optional)) { + if (checkForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional)) { return true; } // Technically, computed properties in ambient contexts is disallowed @@ -5178,21 +5182,21 @@ module ts { var parameter = parameters[i]; if (parameter.dotDotDotToken) { if (i !== (parameterCount - 1)) { - return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } - if (parameter.flags & NodeFlags.QuestionMark) { - return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_be_optional); + if (parameter.questionToken) { + return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_rest_parameter_cannot_be_optional); } if (parameter.initializer) { return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_have_an_initializer); } } - else if (parameter.flags & NodeFlags.QuestionMark || parameter.initializer) { + else if (parameter.questionToken || parameter.initializer) { seenOptionalParameter = true; - if (parameter.flags & NodeFlags.QuestionMark && parameter.initializer) { + if (parameter.questionToken && parameter.initializer) { return grammarErrorOnNode(parameter.name, Diagnostics.Parameter_cannot_have_question_mark_and_initializer); } } @@ -5226,7 +5230,7 @@ module ts { function checkProperty(node: PropertyDeclaration) { if (node.parent.kind === SyntaxKind.ClassDeclaration) { - if (checkForInvalidQuestionMark(node, Diagnostics.A_class_member_cannot_be_declared_optional) || + if (checkForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional) || checkForDisallowedComputedProperty(node.name, Diagnostics.Computed_property_names_are_not_allowed_in_class_property_declarations)) { return true; } @@ -5267,13 +5271,12 @@ module ts { } function checkPropertyAssignment(node: PropertyDeclaration) { - return checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional); + return checkForInvalidQuestionMark(node, node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); } - function checkForInvalidQuestionMark(node: Declaration, message: DiagnosticMessage) { - if (node.flags & NodeFlags.QuestionMark) { - var pos = skipTrivia(sourceText, node.name.end); - return grammarErrorAtPos(pos, "?".length, message); + function checkForInvalidQuestionMark(node: Declaration, questionToken: Node, message: DiagnosticMessage) { + if (questionToken) { + return grammarErrorOnNode(questionToken, message); } } @@ -5315,13 +5318,13 @@ module ts { else { var parameter = accessor.parameters[0]; if (parameter.dotDotDotToken) { - return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_rest_parameter); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter); } else if (parameter.flags & NodeFlags.Modifier) { return grammarErrorOnNode(accessor.name, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } - else if (parameter.flags & NodeFlags.QuestionMark) { - return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter); + else if (parameter.questionToken) { + return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter); } else if (parameter.initializer) { return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer); @@ -5368,7 +5371,7 @@ module ts { } function checkShorthandPropertyAssignment(node: ShortHandPropertyDeclaration): boolean { - return checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional); + return checkForInvalidQuestionMark(node, node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); } function checkSwitchStatement(node: SwitchStatement) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8436399f74f..c2810e01acb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -272,7 +272,6 @@ module ts { export const enum NodeFlags { Export = 0x00000001, // Declarations Ambient = 0x00000002, // Declarations - QuestionMark = 0x00000004, // Parameter/Property/Method Public = 0x00000010, // Property/Method Private = 0x00000020, // Property/Method Protected = 0x00000040, // Property/Method @@ -370,11 +369,13 @@ module ts { export interface ParameterDeclaration extends Declaration { dotDotDotToken?: Node; name: Identifier; + questionToken?: Node; type?: TypeNode | StringLiteralExpression; initializer?: Expression; } export interface PropertyDeclaration extends Declaration, ClassElement { + questionToken?: Node; type?: TypeNode; initializer?: Expression; } @@ -384,6 +385,7 @@ module ts { export interface ShortHandPropertyDeclaration extends Declaration { name: Identifier; + questionToken?: Node; } /** @@ -398,6 +400,7 @@ module ts { _functionLikeDeclarationBrand: any; asteriskToken?: Node; + questionToken?: Node; body?: Block | Expression; } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index f3604b3dfdd..93363b4676b 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -524,7 +524,7 @@ module ts.SignatureHelp { var displayParts = mapToDisplayParts(writer => typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation)); - var isOptional = !!(parameter.valueDeclaration.flags & NodeFlags.QuestionMark); + var isOptional = hasQuestionToken(parameter.valueDeclaration); return { name: parameter.name, diff --git a/tests/baselines/reference/accessorWithRestParam.errors.txt b/tests/baselines/reference/accessorWithRestParam.errors.txt index 6162d5a8238..c6f3ef70563 100644 --- a/tests/baselines/reference/accessorWithRestParam.errors.txt +++ b/tests/baselines/reference/accessorWithRestParam.errors.txt @@ -1,14 +1,14 @@ -tests/cases/compiler/accessorWithRestParam.ts(3,9): error TS1053: A 'set' accessor cannot have rest parameter. -tests/cases/compiler/accessorWithRestParam.ts(4,16): error TS1053: A 'set' accessor cannot have rest parameter. +tests/cases/compiler/accessorWithRestParam.ts(3,11): error TS1053: A 'set' accessor cannot have rest parameter. +tests/cases/compiler/accessorWithRestParam.ts(4,18): error TS1053: A 'set' accessor cannot have rest parameter. ==== tests/cases/compiler/accessorWithRestParam.ts (2 errors) ==== class C { set X(...v) { } - ~ + ~~~ !!! error TS1053: A 'set' accessor cannot have rest parameter. static set X(...v2) { } - ~ + ~~~ !!! error TS1053: A 'set' accessor cannot have rest parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors1.errors.txt b/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors1.errors.txt index 309e731e54f..5934ab52ccf 100644 --- a/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors1.errors.txt +++ b/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors1.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(1,9): error TS1016: A required parameter cannot follow an optional parameter. -tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(2,5): error TS1047: A rest parameter cannot be optional. +tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(2,8): error TS1047: A rest parameter cannot be optional. tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(4,5): error TS1048: A rest parameter cannot have an initializer. tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(7,12): error TS1016: A required parameter cannot follow an optional parameter. @@ -9,7 +9,7 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(7,12): error TS1016 ~~~~ !!! error TS1016: A required parameter cannot follow an optional parameter. (...arg?) => 102; - ~~~ + ~ !!! error TS1047: A rest parameter cannot be optional. (...arg) => 103; (...arg:number [] = []) => 104; diff --git a/tests/baselines/reference/functionOverloadErrorsSyntax.errors.txt b/tests/baselines/reference/functionOverloadErrorsSyntax.errors.txt index 98e7f4cd714..7c83759d02d 100644 --- a/tests/baselines/reference/functionOverloadErrorsSyntax.errors.txt +++ b/tests/baselines/reference/functionOverloadErrorsSyntax.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(2,27): error TS1016: A required parameter cannot follow an optional parameter. tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(5,38): error TS1016: A required parameter cannot follow an optional parameter. -tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(9,28): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(9,25): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts (3 errors) ==== @@ -17,7 +17,7 @@ tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(9,28): error T //Function overload signature with rest param followed by non-optional parameter function fn5(x: string, ...y: any[], z: string); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. function fn5() { } \ No newline at end of file diff --git a/tests/baselines/reference/indexSignatureTypeCheck.errors.txt b/tests/baselines/reference/indexSignatureTypeCheck.errors.txt index 1cc69f6294b..8a020fde5c6 100644 --- a/tests/baselines/reference/indexSignatureTypeCheck.errors.txt +++ b/tests/baselines/reference/indexSignatureTypeCheck.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/indexSignatureTypeCheck.ts(14,6): error TS1019: An index signature parameter cannot have a question mark. -tests/cases/compiler/indexSignatureTypeCheck.ts(15,9): error TS1017: An index signature cannot have a rest parameter. +tests/cases/compiler/indexSignatureTypeCheck.ts(14,8): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/compiler/indexSignatureTypeCheck.ts(15,6): error TS1017: An index signature cannot have a rest parameter. tests/cases/compiler/indexSignatureTypeCheck.ts(16,6): error TS1096: An index signature must have exactly one parameter. tests/cases/compiler/indexSignatureTypeCheck.ts(17,6): error TS1096: An index signature must have exactly one parameter. @@ -19,10 +19,10 @@ tests/cases/compiler/indexSignatureTypeCheck.ts(17,6): error TS1096: An index si interface indexErrors { [p2?: string]; - ~~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. [...p3: any[]]; - ~~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. [p4: string, p5?: string]; ~~ diff --git a/tests/baselines/reference/indexSignatureTypeCheck2.errors.txt b/tests/baselines/reference/indexSignatureTypeCheck2.errors.txt index 25e3ab94280..0fd594268c5 100644 --- a/tests/baselines/reference/indexSignatureTypeCheck2.errors.txt +++ b/tests/baselines/reference/indexSignatureTypeCheck2.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/indexSignatureTypeCheck2.ts(10,6): error TS1019: An index signature parameter cannot have a question mark. -tests/cases/compiler/indexSignatureTypeCheck2.ts(11,9): error TS1017: An index signature cannot have a rest parameter. +tests/cases/compiler/indexSignatureTypeCheck2.ts(10,8): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/compiler/indexSignatureTypeCheck2.ts(11,6): error TS1017: An index signature cannot have a rest parameter. tests/cases/compiler/indexSignatureTypeCheck2.ts(12,6): error TS1096: An index signature must have exactly one parameter. tests/cases/compiler/indexSignatureTypeCheck2.ts(13,6): error TS1096: An index signature must have exactly one parameter. @@ -15,10 +15,10 @@ tests/cases/compiler/indexSignatureTypeCheck2.ts(13,6): error TS1096: An index s interface indexErrors { [p2?: string]; - ~~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. [...p3: any[]]; - ~~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. [p4: string, p5?: string]; ~~ diff --git a/tests/baselines/reference/indexerAsOptional.errors.txt b/tests/baselines/reference/indexerAsOptional.errors.txt index 101c03acccd..cfd2d08cef9 100644 --- a/tests/baselines/reference/indexerAsOptional.errors.txt +++ b/tests/baselines/reference/indexerAsOptional.errors.txt @@ -1,18 +1,18 @@ -tests/cases/compiler/indexerAsOptional.ts(3,6): error TS1019: An index signature parameter cannot have a question mark. -tests/cases/compiler/indexerAsOptional.ts(8,6): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/compiler/indexerAsOptional.ts(3,9): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/compiler/indexerAsOptional.ts(8,9): error TS1019: An index signature parameter cannot have a question mark. ==== tests/cases/compiler/indexerAsOptional.ts (2 errors) ==== interface indexSig { //Index signatures can't be optional [idx?: number]: any; //err - ~~~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. } class indexSig2 { //Index signatures can't be optional [idx?: number]: any //err - ~~~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. } \ No newline at end of file diff --git a/tests/baselines/reference/indexerSignatureWithRestParam.errors.txt b/tests/baselines/reference/indexerSignatureWithRestParam.errors.txt index 4743ed8e91c..08c65816416 100644 --- a/tests/baselines/reference/indexerSignatureWithRestParam.errors.txt +++ b/tests/baselines/reference/indexerSignatureWithRestParam.errors.txt @@ -1,16 +1,16 @@ -tests/cases/compiler/indexerSignatureWithRestParam.ts(2,9): error TS1017: An index signature cannot have a rest parameter. -tests/cases/compiler/indexerSignatureWithRestParam.ts(6,9): error TS1017: An index signature cannot have a rest parameter. +tests/cases/compiler/indexerSignatureWithRestParam.ts(2,6): error TS1017: An index signature cannot have a rest parameter. +tests/cases/compiler/indexerSignatureWithRestParam.ts(6,6): error TS1017: An index signature cannot have a rest parameter. ==== tests/cases/compiler/indexerSignatureWithRestParam.ts (2 errors) ==== interface I { [...x]: string; - ~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. } class C { [...x]: string - ~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/parserIndexSignature1.errors.txt b/tests/baselines/reference/parserIndexSignature1.errors.txt index 74f5d0e0921..cde7259c7bd 100644 --- a/tests/baselines/reference/parserIndexSignature1.errors.txt +++ b/tests/baselines/reference/parserIndexSignature1.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature1.ts(2,7): error TS1017: An index signature cannot have a rest parameter. +tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature1.ts(2,4): error TS1017: An index signature cannot have a rest parameter. ==== tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature1.ts (1 errors) ==== interface I { [...a] - ~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/parserIndexSignature3.errors.txt b/tests/baselines/reference/parserIndexSignature3.errors.txt index bc552fd6a1d..27310e4d0a4 100644 --- a/tests/baselines/reference/parserIndexSignature3.errors.txt +++ b/tests/baselines/reference/parserIndexSignature3.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature3.ts(2,4): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature3.ts(2,5): error TS1019: An index signature parameter cannot have a question mark. ==== tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature3.ts (1 errors) ==== interface I { [a?] - ~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration17.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration17.errors.txt index 6edb9b98b7b..2d7f6e3be30 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration17.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration17.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration17.ts(2,8): error TS1051: A 'set' accessor cannot have an optional parameter. +tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration17.ts(2,13): error TS1051: A 'set' accessor cannot have an optional parameter. ==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration17.ts (1 errors) ==== class C { set Foo(a?: number) { } - ~~~ + ~ !!! error TS1051: A 'set' accessor cannot have an optional parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration18.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration18.errors.txt index 54d39a6d663..8296a087bab 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration18.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration18.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration18.ts(2,8): error TS1053: A 'set' accessor cannot have rest parameter. +tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration18.ts(2,12): error TS1053: A 'set' accessor cannot have rest parameter. ==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration18.ts (1 errors) ==== class C { set Foo(...a) { } - ~~~ + ~~~ !!! error TS1053: A 'set' accessor cannot have rest parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList1.errors.txt b/tests/baselines/reference/parserParameterList1.errors.txt index 3b01ee02168..a7e9a533f63 100644 --- a/tests/baselines/reference/parserParameterList1.errors.txt +++ b/tests/baselines/reference/parserParameterList1.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList1.ts(2,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList1.ts(2,6): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList1.ts (1 errors) ==== class C { F(...A, B) { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. } \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList11.errors.txt b/tests/baselines/reference/parserParameterList11.errors.txt index 1fcede6c398..2cb8def201d 100644 --- a/tests/baselines/reference/parserParameterList11.errors.txt +++ b/tests/baselines/reference/parserParameterList11.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList11.ts(1,5): error TS1047: A rest parameter cannot be optional. +tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList11.ts(1,8): error TS1047: A rest parameter cannot be optional. ==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList11.ts (1 errors) ==== (...arg?) => 102; - ~~~ + ~ !!! error TS1047: A rest parameter cannot be optional. \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList9.errors.txt b/tests/baselines/reference/parserParameterList9.errors.txt index 2db96373cd0..5f670148faa 100644 --- a/tests/baselines/reference/parserParameterList9.errors.txt +++ b/tests/baselines/reference/parserParameterList9.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList9.ts(2,11): error TS1047: A rest parameter cannot be optional. +tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList9.ts(2,14): error TS1047: A rest parameter cannot be optional. ==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList9.ts (1 errors) ==== class C { foo(...bar?) { } - ~~~ + ~ !!! error TS1047: A rest parameter cannot be optional. } \ No newline at end of file diff --git a/tests/baselines/reference/restParamAsOptional.errors.txt b/tests/baselines/reference/restParamAsOptional.errors.txt index ac061e5d98e..9ab684f0944 100644 --- a/tests/baselines/reference/restParamAsOptional.errors.txt +++ b/tests/baselines/reference/restParamAsOptional.errors.txt @@ -1,10 +1,10 @@ -tests/cases/compiler/restParamAsOptional.ts(1,15): error TS1047: A rest parameter cannot be optional. +tests/cases/compiler/restParamAsOptional.ts(1,16): error TS1047: A rest parameter cannot be optional. tests/cases/compiler/restParamAsOptional.ts(2,16): error TS1048: A rest parameter cannot have an initializer. ==== tests/cases/compiler/restParamAsOptional.ts (2 errors) ==== function f(...x?) { } - ~ + ~ !!! error TS1047: A rest parameter cannot be optional. function f2(...x = []) { } ~ diff --git a/tests/baselines/reference/restParameterNotLast.errors.txt b/tests/baselines/reference/restParameterNotLast.errors.txt index a5b91d05795..0d69ef154ba 100644 --- a/tests/baselines/reference/restParameterNotLast.errors.txt +++ b/tests/baselines/reference/restParameterNotLast.errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/restParameterNotLast.ts(1,15): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/compiler/restParameterNotLast.ts(1,12): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/compiler/restParameterNotLast.ts (1 errors) ==== function f(...x, y) { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. \ No newline at end of file diff --git a/tests/baselines/reference/restParameterWithoutAnnotationIsAnyArray.errors.txt b/tests/baselines/reference/restParameterWithoutAnnotationIsAnyArray.errors.txt index e021204341e..0177f1e9a1c 100644 --- a/tests/baselines/reference/restParameterWithoutAnnotationIsAnyArray.errors.txt +++ b/tests/baselines/reference/restParameterWithoutAnnotationIsAnyArray.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(5,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(13,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(23,24): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(5,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(13,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(23,21): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts (3 errors) ==== @@ -9,7 +9,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWith function foo(...x) { } var f = function foo(...x) { } var f2 = (...x, ...y) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. class C { @@ -19,7 +19,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWith interface I { (...x); foo(...x, ...y); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. } @@ -31,7 +31,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWith var b = { foo(...x) { }, a: function foo(...x, ...y) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. b: (...x) => { } } diff --git a/tests/baselines/reference/restParametersOfNonArrayTypes.errors.txt b/tests/baselines/reference/restParametersOfNonArrayTypes.errors.txt index 2c7db9973d9..12cbd865d1c 100644 --- a/tests/baselines/reference/restParametersOfNonArrayTypes.errors.txt +++ b/tests/baselines/reference/restParametersOfNonArrayTypes.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(5,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(13,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(23,24): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(5,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(13,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(23,21): error TS1014: A rest parameter must be last in a parameter list. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(3,14): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(4,22): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(5,11): error TS2370: A rest parameter must be of an array type. @@ -27,7 +27,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. var f2 = (...x: Date, ...y: boolean) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -45,7 +45,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. foo(...x: number, ...y: number); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -67,7 +67,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. a: function foo(...x: number, ...y: Date) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. diff --git a/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt b/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt index 592993076fd..eef052e5cdf 100644 --- a/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt +++ b/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,24): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,24): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,21): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,21): error TS1014: A rest parameter must be last in a parameter list. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(7,14): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(8,22): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,11): error TS2370: A rest parameter must be of an array type. @@ -48,7 +48,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. var f2 = (...x: MyThing, ...y: MyThing) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -66,7 +66,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. foo(...x: MyThing, ...y: MyThing); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -88,7 +88,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. a: function foo(...x: MyThing, ...y: MyThing) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -109,7 +109,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. var f4 = (...x: MyThing2, ...y: MyThing2) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -127,7 +127,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. foo(...x: MyThing2, ...y: MyThing2); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -149,7 +149,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. a: function foo(...x: MyThing2, ...y: MyThing2) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. diff --git a/tests/baselines/reference/restParametersWithArrayTypeAnnotations.errors.txt b/tests/baselines/reference/restParametersWithArrayTypeAnnotations.errors.txt index 65afe52efa1..06b2caefb9d 100644 --- a/tests/baselines/reference/restParametersWithArrayTypeAnnotations.errors.txt +++ b/tests/baselines/reference/restParametersWithArrayTypeAnnotations.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(5,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(13,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(23,24): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(32,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(40,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(50,24): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(5,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(13,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(23,21): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(32,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(40,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(50,21): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts (6 errors) ==== @@ -12,7 +12,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit function foo(...x: number[]) { } var f = function foo(...x: number[]) { } var f2 = (...x: number[], ...y: number[]) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. class C { @@ -22,7 +22,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit interface I { (...x: number[]); foo(...x: number[], ...y: number[]); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. } @@ -34,7 +34,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit var b = { foo(...x: number[]) { }, a: function foo(...x: number[], ...y: number[]) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. b: (...x: number[]) => { } } @@ -45,7 +45,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit function foo2(...x: Array) { } var f3 = function foo(...x: Array) { } var f4 = (...x: Array, ...y: Array) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. class C2 { @@ -55,7 +55,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit interface I2 { (...x: Array); foo(...x: Array, ...y: Array); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. } @@ -67,7 +67,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit var b2 = { foo(...x: Array) { }, a: function foo(...x: Array, ...y: Array) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. b: (...x: Array) => { } } \ No newline at end of file From 2459632a6234d871ae0d34519a7345d5d95254cb Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:20:03 -0800 Subject: [PATCH 23/41] Simplifying the signature parsing code. --- src/compiler/parser.ts | 64 ++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 97b973eb8d0..5809eb8d771 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1894,22 +1894,17 @@ module ts { return parseInitializer(/*inParameter*/ true); } - function parseSignature(kind: SyntaxKind, returnToken: SyntaxKind, returnTokenRequired: boolean, yieldAndGeneratorParameterContext: boolean): ParsedSignature { + function parseSignature(yieldAndGeneratorParameterContext: boolean): ParsedSignature { var signature = {}; - fillSignature(kind, returnToken, returnTokenRequired, yieldAndGeneratorParameterContext, signature); + fillSignature(SyntaxKind.ColonToken, yieldAndGeneratorParameterContext, signature); return signature; } function fillSignature( - kind: SyntaxKind, returnToken: SyntaxKind, - returnTokenRequired: boolean, yieldAndGeneratorParameterContext: boolean, signature: ParsedSignature): void { - - if (kind === SyntaxKind.ConstructSignature) { - parseExpected(SyntaxKind.NewKeyword); - } + var returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken; signature.typeParameters = parseTypeParameters(); signature.parameters = parseParameterList(yieldAndGeneratorParameterContext); @@ -1960,9 +1955,12 @@ module ts { return createMissingList(); } - function parseSignatureMember(kind: SyntaxKind, returnToken: SyntaxKind): SignatureDeclaration { + function parseSignatureMember(kind: SyntaxKind): SignatureDeclaration { var node = createNode(kind); - fillSignature(kind, returnToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false, node); + if (kind === SyntaxKind.ConstructSignature) { + parseExpected(SyntaxKind.NewKeyword); + } + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node); parseSemicolon(); return finishNode(node); } @@ -2047,7 +2045,7 @@ module ts { // Method signatues don't exist in expression contexts. So they have neither // [Yield] nor [GeneratorParameter] - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false, method); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, method); parseSemicolon(); return finishNode(method); @@ -2069,8 +2067,12 @@ module ts { case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties return true; default: - return isLiteralPropertyName() && lookAhead(() => nextToken() === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken || token === SyntaxKind.QuestionToken || - token === SyntaxKind.ColonToken || canParseSemicolon()); + return isLiteralPropertyName() && lookAhead(() => + nextToken() === SyntaxKind.OpenParenToken || + token === SyntaxKind.LessThanToken || + token === SyntaxKind.QuestionToken || + token === SyntaxKind.ColonToken || + canParseSemicolon()); } } @@ -2078,13 +2080,13 @@ module ts { switch (token) { case SyntaxKind.OpenParenToken: case SyntaxKind.LessThanToken: - return parseSignatureMember(SyntaxKind.CallSignature, SyntaxKind.ColonToken); + return parseSignatureMember(SyntaxKind.CallSignature); case SyntaxKind.OpenBracketToken: // Indexer or computed property return isIndexSignature() ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined) : parsePropertyOrMethod(); case SyntaxKind.NewKeyword: if (lookAhead(() => nextToken() === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken)) { - return parseSignatureMember(SyntaxKind.ConstructSignature, SyntaxKind.ColonToken); + return parseSignatureMember(SyntaxKind.ConstructSignature); } case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -2098,11 +2100,11 @@ module ts { function parseTypeLiteral(): TypeLiteralNode { var node = createNode(SyntaxKind.TypeLiteral); - node.members = parseObjectType(); + node.members = parseObjectTypeMembers(); return finishNode(node); } - function parseObjectType(): NodeArray { + function parseObjectTypeMembers(): NodeArray { var members: NodeArray; if (parseExpected(SyntaxKind.OpenBraceToken)) { members = parseList(ParsingContext.TypeMembers, /*checkForStrictMode*/ false, parseTypeMember); @@ -2129,10 +2131,12 @@ module ts { return finishNode(node); } - function parseFunctionType(typeKind: SyntaxKind): FunctionOrConstructorTypeNode { - var node = createNode(typeKind); - fillSignature(typeKind === SyntaxKind.FunctionType ? SyntaxKind.CallSignature : SyntaxKind.ConstructSignature, - SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true, /*yieldAndGeneratorParameterContext:*/ false, node); + function parseFunctionType(kind: SyntaxKind): FunctionOrConstructorTypeNode { + var node = createNode(kind); + if (kind === SyntaxKind.ConstructorType) { + parseExpected(SyntaxKind.NewKeyword); + } + fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, node); return finishNode(node); } @@ -2510,7 +2514,7 @@ module ts { if (triState === Tristate.True) { // Arrow function are never generators. - var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /*returnTokenRequired:*/ false, /*yieldAndGeneratorParameterContext:*/ false); + var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ false); // If we have an arrow, then try to parse the body. // Even if not, try to parse if we have an opening brace, just in case we're in an error state. @@ -2614,7 +2618,7 @@ module ts { function tryParseSignatureIfArrowOrBraceFollows(): ParsedSignature { return tryParse(() => { // Arrow functions are never generators. - var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false); + var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ false); // Parsing a signature isn't enough. // Parenthesized arrow signatures often look like other valid expressions. @@ -3128,7 +3132,7 @@ module ts { if (asteriskToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { node = createNode(SyntaxKind.PropertyAssignment, nodePos); node.name = propertyName; - var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken); + var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ !!asteriskToken); var body = parseFunctionBlock(!!asteriskToken, /* ignoreMissingOpenBrace */ false); // do not propagate property name as name for function expression @@ -3192,7 +3196,7 @@ module ts { parseExpected(SyntaxKind.FunctionKeyword); var asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); var name = asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier(); - var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken); + var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ !!asteriskToken); var body = parseFunctionBlock(/*allowYield:*/ !!asteriskToken, /* ignoreMissingOpenBrace */ false); return makeFunctionExpression(SyntaxKind.FunctionExpression, pos, asteriskToken, name, sig, body); @@ -3667,7 +3671,7 @@ module ts { parseExpected(SyntaxKind.FunctionKeyword); node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); node.name = parseIdentifier(); - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, node); node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken); return finishNode(node); } @@ -3676,7 +3680,7 @@ module ts { var node = createNode(SyntaxKind.Constructor, pos); setModifiers(node, modifiers); parseExpected(SyntaxKind.ConstructorKeyword); - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node); node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false); return finishNode(node); } @@ -3694,7 +3698,7 @@ module ts { method.asteriskToken = asteriskToken; method.name = name; method.questionToken = questionToken; - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, method); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, method); method.body = parseFunctionBlockOrSemicolon(!!asteriskToken); return finishNode(method); } @@ -3714,7 +3718,7 @@ module ts { var node = createNode(kind, fullStart); setModifiers(node, modifiers); node.name = parsePropertyName(); - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node); node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false); return finishNode(node); } @@ -3893,7 +3897,7 @@ module ts { node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause:*/ false); - node.members = parseObjectType(); + node.members = parseObjectTypeMembers(); return finishNode(node); } From af62715e8dc372114ff43e99c6aa383c3156bf03 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:30:22 -0800 Subject: [PATCH 24/41] Use helper function. Rename some functions to be clearer. --- src/compiler/parser.ts | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5809eb8d771..6549b86122d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1851,7 +1851,7 @@ module ts { function parseParameter(): ParameterDeclaration { var node = createNode(SyntaxKind.Parameter); setModifiers(node, parseModifiers()); - node.dotDotDotToken = token === SyntaxKind.DotDotDotToken ? parseTokenNode() : undefined; + node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); // SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3 // [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt @@ -1873,7 +1873,7 @@ module ts { nextToken(); } - node.questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; + node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken); node.type = parseParameterType(); node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) @@ -2036,7 +2036,7 @@ module ts { function parsePropertyOrMethod(): Declaration { var fullStart = scanner.getStartPos(); var name = parsePropertyName(); - var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; + var questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { var method = createNode(SyntaxKind.Method, fullStart); @@ -2123,7 +2123,7 @@ module ts { return finishNode(node); } - function parseParenType(): ParenthesizedTypeNode { + function parseParenthesizedType(): ParenthesizedTypeNode { var node = createNode(SyntaxKind.ParenthesizedType); parseExpected(SyntaxKind.OpenParenToken); node.type = parseType(); @@ -2131,7 +2131,7 @@ module ts { return finishNode(node); } - function parseFunctionType(kind: SyntaxKind): FunctionOrConstructorTypeNode { + function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode { var node = createNode(kind); if (kind === SyntaxKind.ConstructorType) { parseExpected(SyntaxKind.NewKeyword); @@ -2163,7 +2163,7 @@ module ts { case SyntaxKind.OpenBracketToken: return parseTupleType(); case SyntaxKind.OpenParenToken: - return parseParenType(); + return parseParenthesizedType(); default: return parseTypeReference(); } @@ -2194,7 +2194,7 @@ module ts { } } - function parsePrimaryType(): TypeNode { + function parseArrayTypeOrHigher(): TypeNode { var type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { parseExpected(SyntaxKind.CloseBracketToken); @@ -2205,13 +2205,13 @@ module ts { return type; } - function parseUnionType(): TypeNode { - var type = parsePrimaryType(); + function parseUnionTypeOrHigher(): TypeNode { + var type = parseArrayTypeOrHigher(); if (token === SyntaxKind.BarToken) { var types = >[type]; types.pos = type.pos; while (parseOptional(SyntaxKind.BarToken)) { - types.push(parsePrimaryType()); + types.push(parseArrayTypeOrHigher()); } types.end = getNodeEnd(); var node = createNode(SyntaxKind.UnionType, type.pos); @@ -2272,12 +2272,12 @@ module ts { function parseTypeWorker(): TypeNode { if (isStartOfFunctionType()) { - return parseFunctionType(SyntaxKind.FunctionType); + return parseFunctionOrConstructorType(SyntaxKind.FunctionType); } if (token === SyntaxKind.NewKeyword) { - return parseFunctionType(SyntaxKind.ConstructorType); + return parseFunctionOrConstructorType(SyntaxKind.ConstructorType); } - return parseUnionType(); + return parseUnionTypeOrHigher(); } function parseTypeAnnotation(): TypeNode { @@ -2486,9 +2486,8 @@ module ts { function parseSimpleArrowFunctionExpression(identifier: Identifier): Expression { Debug.assert(token === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); - parseExpected(SyntaxKind.EqualsGreaterThanToken); - var parameter = createNode(SyntaxKind.Parameter, identifier.pos); + parseExpected(SyntaxKind.EqualsGreaterThanToken); parameter.name = identifier; finishNode(parameter); @@ -2497,7 +2496,7 @@ module ts { parameters.pos = parameter.pos; parameters.end = parameter.end; - var signature = { parameters: parameters }; + var signature = { parameters: parameters }; return parseArrowExpressionTail(identifier.pos, signature); } @@ -3145,7 +3144,7 @@ module ts { } // Disallowing of optional property assignments happens in the grammar checker. - var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; + var questionToken = parseOptionalToken(SyntaxKind.QuestionToken); // Parse to check if it is short-hand property assignment or normal property assignment if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) { @@ -3691,7 +3690,7 @@ module ts { // Note: this is not legal as per the grammar. But we allow it in the parser and // report an error in the grammar checker. - var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; + var questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (asteriskToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { var method = createNode(SyntaxKind.Method, fullStart); setModifiers(method, modifiers); From b5c3cd8d4a73033d9dc7f575e41aeca5d9fa1f4d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:39:10 -0800 Subject: [PATCH 25/41] Simplify code. --- src/compiler/parser.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6549b86122d..a89a8fd52fb 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2763,9 +2763,8 @@ module ts { function parsePrefixUnaryExpression() { var node = createNode(SyntaxKind.PrefixUnaryExpression); - var operator = token; + node.operator = token; nextToken(); - node.operator = operator; node.operand = parseUnaryExpressionOrHigher(); return finishNode(node); } @@ -2859,13 +2858,9 @@ module ts { // the last two CallExpression productions. Or we have a MemberExpression which either // completes the LeftHandSideExpression, or starts the beginning of the first four // CallExpression productions. - var expression: MemberExpression; - if (token === SyntaxKind.SuperKeyword) { - expression = parseSuperExpression(); - } - else { - expression = parseMemberExpressionOrHigher(); - } + var expression = token === SyntaxKind.SuperKeyword + ? parseSuperExpression() + : parseMemberExpressionOrHigher(); // Now, we *may* be complete. However, we might have consumed the start of a // CallExpression. As such, we need to consume the rest of it here to be complete. From 44627f859f99c2b8b211a6871726bdab13d8af16 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:50:03 -0800 Subject: [PATCH 26/41] Simplify parsing code. --- src/compiler/checker.ts | 7 ++++--- src/compiler/emitter.ts | 2 +- src/compiler/parser.ts | 21 ++++++++++++--------- src/compiler/types.ts | 8 +++++++- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9fca10b7341..64ed5f25bca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7743,13 +7743,14 @@ module ts { function checkSwitchStatement(node: SwitchStatement) { var expressionType = checkExpression(node.expression); forEach(node.clauses, clause => { - if (fullTypeCheck && clause.expression) { + if (fullTypeCheck && clause.kind === SyntaxKind.CaseClause) { + var caseClause = clause; // TypeScript 1.0 spec (April 2014):5.9 // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. - var caseType = checkExpression(clause.expression); + var caseType = checkExpression(caseClause.expression); if (!isTypeAssignableTo(expressionType, caseType)) { // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails - checkTypeAssignableTo(caseType, expressionType, clause.expression, /*headMessage*/ undefined); + checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } } forEach(clause.statements, checkSourceElement); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index ff52209ba69..b065287b7d2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2624,7 +2624,7 @@ module ts { function emitCaseOrDefaultClause(node: CaseOrDefaultClause) { if (node.kind === SyntaxKind.CaseClause) { write("case "); - emit(node.expression); + emit((node).expression); write(":"); } else { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a89a8fd52fb..a45de6309d4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -353,9 +353,10 @@ module ts { return child((node).expression) || children((node).clauses); case SyntaxKind.CaseClause: + return child((node).expression) || + children((node).statements); case SyntaxKind.DefaultClause: - return child((node).expression) || - children((node).statements); + return children((node).statements); case SyntaxKind.LabeledStatement: return child((node).label) || child((node).statement); @@ -3215,7 +3216,11 @@ module ts { var node = createNode(SyntaxKind.NewExpression); parseExpected(SyntaxKind.NewKeyword); node.expression = parseMemberExpressionOrHigher(); - if (parseOptional(SyntaxKind.OpenParenToken) || (token === SyntaxKind.LessThanToken && (node.typeArguments = tryParse(parseTypeArgumentsAndOpenParen)))) { + if (token === SyntaxKind.LessThanToken) { + node.typeArguments = tryParse(parseTypeArgumentsAndOpenParen); + } + + if (node.typeArguments || parseOptional(SyntaxKind.OpenParenToken)) { node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression); parseExpected(SyntaxKind.CloseParenToken); } @@ -3381,8 +3386,8 @@ module ts { return finishNode(node); } - function parseCaseClause(): CaseOrDefaultClause { - var node = createNode(SyntaxKind.CaseClause); + function parseCaseClause(): CaseClause { + var node = createNode(SyntaxKind.CaseClause); parseExpected(SyntaxKind.CaseKeyword); node.expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.ColonToken); @@ -3390,8 +3395,8 @@ module ts { return finishNode(node); } - function parseDefaultClause(): CaseOrDefaultClause { - var node = createNode(SyntaxKind.DefaultClause); + function parseDefaultClause(): DefaultClause { + var node = createNode(SyntaxKind.DefaultClause); parseExpected(SyntaxKind.DefaultKeyword); parseExpected(SyntaxKind.ColonToken); node.statements = parseList(ParsingContext.SwitchClauseStatements, /*checkForStrictMode*/ false, parseStatement); @@ -3409,9 +3414,7 @@ module ts { node.expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); parseExpected(SyntaxKind.OpenBraceToken); - node.clauses = parseList(ParsingContext.SwitchClauses, /*checkForStrictMode*/ false, parseCaseOrDefaultClause); - parseExpected(SyntaxKind.CloseBraceToken); return finishNode(node); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c2810e01acb..a042ceae14d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -671,11 +671,17 @@ module ts { clauses: NodeArray; } - export interface CaseOrDefaultClause extends Node { + export interface CaseClause extends Node { expression?: Expression; statements: NodeArray; } + export interface DefaultClause extends Node { + statements: NodeArray; + } + + export type CaseOrDefaultClause = CaseClause | DefaultClause; + export interface LabeledStatement extends Statement { label: Identifier; statement: Statement; From 08165c0b17f18972b774c3fd6d316de39260ba71 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 1 Dec 2014 23:15:13 -0800 Subject: [PATCH 27/41] Ensure getEmitOutput only check the file requested --- src/compiler/checker.ts | 13 ++--- src/compiler/emitter.ts | 35 +++++++++---- src/compiler/types.ts | 3 +- src/harness/fourslash.ts | 7 ++- src/harness/harness.ts | 1 - src/services/services.ts | 52 ++++--------------- ...mitOutputWithEarlySyntacticErrors.baseline | 2 + ...ithSemanticErrorsForMultipleFiles.baseline | 8 +++ ...thSemanticErrorsForMultipleFiles2.baseline | 8 +++ ...thSyntacticErrorsForMultipleFiles.baseline | 6 +++ ...hSyntacticErrorsForMultipleFiles2.baseline | 2 + .../getEmitOutputWithEarlySemanticErrors.ts | 10 ++++ ...utputWithSemanticErrorsForMultipleFiles.ts | 16 ++++++ ...tputWithSemanticErrorsForMultipleFiles2.ts | 17 ++++++ ...tputWithSyntacticErrorsForMultipleFiles.ts | 15 ++++++ ...putWithSyntacticErrorsForMultipleFiles2.ts | 16 ++++++ 16 files changed, 142 insertions(+), 69 deletions(-) create mode 100644 tests/baselines/reference/getEmitOutputWithEarlySyntacticErrors.baseline create mode 100644 tests/baselines/reference/getEmitOutputWithSemanticErrorsForMultipleFiles.baseline create mode 100644 tests/baselines/reference/getEmitOutputWithSemanticErrorsForMultipleFiles2.baseline create mode 100644 tests/baselines/reference/getEmitOutputWithSyntacticErrorsForMultipleFiles.baseline create mode 100644 tests/baselines/reference/getEmitOutputWithSyntacticErrorsForMultipleFiles2.baseline create mode 100644 tests/cases/fourslash/getEmitOutputWithEarlySemanticErrors.ts create mode 100644 tests/cases/fourslash/getEmitOutputWithSemanticErrorsForMultipleFiles.ts create mode 100644 tests/cases/fourslash/getEmitOutputWithSemanticErrorsForMultipleFiles2.ts create mode 100644 tests/cases/fourslash/getEmitOutputWithSyntacticErrorsForMultipleFiles.ts create mode 100644 tests/cases/fourslash/getEmitOutputWithSyntacticErrorsForMultipleFiles2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a663b038844..edf966a2fe1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -85,7 +85,6 @@ module ts { getDiagnostics, getDeclarationDiagnostics, getGlobalDiagnostics, - checkProgram, getParentOfSymbol, getNarrowedTypeOfSymbol, getDeclaredTypeOfSymbol, @@ -8634,10 +8633,6 @@ module ts { } } - function checkProgram() { - forEach(program.getSourceFiles(), checkSourceFile); - } - function getSortedDiagnostics(): Diagnostic[]{ Debug.assert(fullTypeCheck, "diagnostics are available only in the full typecheck mode"); @@ -8650,12 +8645,11 @@ module ts { } function getDiagnostics(sourceFile?: SourceFile): Diagnostic[]{ - if (sourceFile) { checkSourceFile(sourceFile); return filter(getSortedDiagnostics(), d => d.file === sourceFile); } - checkProgram(); + forEach(program.getSourceFiles(), checkSourceFile); return getSortedDiagnostics(); } @@ -9173,9 +9167,9 @@ module ts { return isImportResolvedToValue(getSymbolOfNode(node)); } - function hasSemanticErrors() { + function hasSemanticErrors(sourceFile?: SourceFile) { // Return true if there is any semantic error in a file or globally - return getDiagnostics().length > 0 || getGlobalDiagnostics().length > 0; + return getDiagnostics(sourceFile).length > 0 || getGlobalDiagnostics().length > 0; } function isEmitBlocked(sourceFile?: SourceFile): boolean { @@ -9293,7 +9287,6 @@ module ts { function invokeEmitter(targetSourceFile?: SourceFile) { var resolver = createResolver(); - checkProgram(); return emitFiles(resolver, targetSourceFile); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fab0433890a..cdb36cc5ac9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3791,20 +3791,14 @@ module ts { } } - var hasSemanticErrors = resolver.hasSemanticErrors(); - var isEmitBlocked = resolver.isEmitBlocked(targetSourceFile); - - function emitFile(jsFilePath: string, sourceFile?: SourceFile) { - if (!isEmitBlocked) { - emitJavaScript(jsFilePath, sourceFile); - if (!hasSemanticErrors && compilerOptions.declaration) { - writeDeclarationFile(jsFilePath, sourceFile); - } - } - } + var hasSemanticErrors: boolean = false; + var isEmitBlocked: boolean = false; if (targetSourceFile === undefined) { // No targetSourceFile is specified (e.g. calling emitter from batch compiler) + hasSemanticErrors = resolver.hasSemanticErrors(); + isEmitBlocked = resolver.isEmitBlocked(); + forEach(program.getSourceFiles(), sourceFile => { if (shouldEmitToOwnFile(sourceFile, compilerOptions)) { var jsFilePath = getOwnEmitOutputFilePath(sourceFile, program, ".js"); @@ -3820,16 +3814,35 @@ module ts { // targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service) if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) { // If shouldEmitToOwnFile returns true or targetSourceFile is an external module file, then emit targetSourceFile in its own output file + hasSemanticErrors = resolver.hasSemanticErrors(targetSourceFile); + isEmitBlocked = resolver.isEmitBlocked(targetSourceFile); + var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, program, ".js"); emitFile(jsFilePath, targetSourceFile); } else if (!isDeclarationFile(targetSourceFile) && compilerOptions.out) { // Otherwise, if --out is specified and targetSourceFile is not a declaration file, // Emit all, non-external-module file, into one single output file + forEach(program.getSourceFiles(), sourceFile => { + if (!shouldEmitToOwnFile(sourceFile, compilerOptions)) { + hasSemanticErrors = hasSemanticErrors || resolver.hasSemanticErrors(sourceFile); + isEmitBlocked = isEmitBlocked || resolver.isEmitBlocked(sourceFile); + } + }); + emitFile(compilerOptions.out); } } + function emitFile(jsFilePath: string, sourceFile?: SourceFile) { + if (!isEmitBlocked) { + emitJavaScript(jsFilePath, sourceFile); + if (!hasSemanticErrors && compilerOptions.declaration) { + writeDeclarationFile(jsFilePath, sourceFile); + } + } + } + // Sort and make the unique list of diagnostics diagnostics.sort(compareDiagnostics); diagnostics = deduplicateSortedDiagnostics(diagnostics); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 277e2cce5ff..0c3f3d96d98 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -861,7 +861,6 @@ module ts { getIdentifierCount(): number; getSymbolCount(): number; getTypeCount(): number; - checkProgram(): void; emitFiles(targetSourceFile?: SourceFile): EmitResult; getParentOfSymbol(symbol: Symbol): Symbol; getNarrowedTypeOfSymbol(symbol: Symbol, node: Node): Type; @@ -973,7 +972,7 @@ module ts { isTopLevelValueImportWithEntityName(node: ImportDeclaration): boolean; getNodeCheckFlags(node: Node): NodeCheckFlags; getEnumMemberValue(node: EnumMember): number; - hasSemanticErrors(): boolean; + hasSemanticErrors(sourceFile?: SourceFile): boolean; isDeclarationVisible(node: Declaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableOrParameterDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 05e65f5648f..7e364730ede 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2217,11 +2217,10 @@ module FourSlash { // TODO (drosen): We need to enforce checking on these tests. var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true }, host); var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true); - checker.checkProgram(); - var errs = program.getDiagnostics().concat(checker.getDiagnostics()); - if (errs.length > 0) { - throw new Error('Error compiling ' + fileName + ': ' + errs.map(e => e.messageText).join('\r\n')); + var errors = program.getDiagnostics().concat(checker.getDiagnostics()); + if (errors.length > 0) { + throw new Error('Error compiling ' + fileName + ': ' + errors.map(e => e.messageText).join('\r\n')); } checker.emitFiles(); result = result || ''; // Might have an empty fourslash file diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 640d5f0ae53..c0d3ddedce3 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -801,7 +801,6 @@ module Harness { useCaseSensitiveFileNames)); var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true); - checker.checkProgram(); var isEmitBlocked = checker.isEmitBlocked(); diff --git a/src/services/services.ts b/src/services/services.ts index 8bbc03aad6f..a191e5af83c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4665,18 +4665,14 @@ module ts { function getEmitOutput(filename: string): EmitOutput { synchronizeHostData(); + filename = normalizeSlashes(filename); - var compilerOptions = program.getCompilerOptions(); - var targetSourceFile = program.getSourceFile(filename); // Current selected file to be output - // If --out flag is not specified, shouldEmitToOwnFile is true. Otherwise shouldEmitToOwnFile is false. - var shouldEmitToOwnFile = ts.shouldEmitToOwnFile(targetSourceFile, compilerOptions); - var emitOutput: EmitOutput = { - outputFiles: [], - emitOutputStatus: undefined, - }; + var sourceFile = getSourceFile(filename); + + var outputFiles: OutputFile[] = []; function getEmitOutputWriter(filename: string, data: string, writeByteOrderMark: boolean) { - emitOutput.outputFiles.push({ + outputFiles.push({ name: filename, writeByteOrderMark: writeByteOrderMark, text: data @@ -4686,41 +4682,15 @@ module ts { // Initialize writer for CompilerHost.writeFile writer = getEmitOutputWriter; - var containSyntacticErrors = false; - - if (shouldEmitToOwnFile) { - // Check only the file we want to emit - containSyntacticErrors = containErrors(program.getDiagnostics(targetSourceFile)); - } else { - // Check the syntactic of only sourceFiles that will get emitted into single output - // Terminate the process immediately if we encounter a syntax error from one of the sourceFiles - containSyntacticErrors = forEach(program.getSourceFiles(), sourceFile => { - if (!isExternalModuleOrDeclarationFile(sourceFile)) { - // If emit to a single file then we will check all files that do not have external module - return containErrors(program.getDiagnostics(sourceFile)); - } - return false; - }); - } - - if (containSyntacticErrors) { - // If there is a syntax error, terminate the process and report outputStatus - emitOutput.emitOutputStatus = EmitReturnStatus.AllOutputGenerationSkipped; - // Reset writer back to undefined to make sure that we produce an error message - // if CompilerHost.writeFile is called when we are not in getEmitOutput - writer = undefined; - return emitOutput; - } - - // Perform semantic and force a type check before emit to ensure that all symbols are updated - // EmitFiles will report if there is an error from TypeChecker and Emitter - // Depend whether we will have to emit into a single file or not either emit only selected file in the project, emit all files into a single file - var emitFilesResult = getFullTypeCheckChecker().emitFiles(targetSourceFile); - emitOutput.emitOutputStatus = emitFilesResult.emitResultStatus; + var emitOutput = getFullTypeCheckChecker().emitFiles(sourceFile); // Reset writer back to undefined to make sure that we produce an error message if CompilerHost.writeFile method is called when we are not in getEmitOutput writer = undefined; - return emitOutput; + + return { + outputFiles, + emitOutputStatus: emitOutput.emitResultStatus + }; } function getMeaningFromDeclaration(node: Node): SemanticMeaning { diff --git a/tests/baselines/reference/getEmitOutputWithEarlySyntacticErrors.baseline b/tests/baselines/reference/getEmitOutputWithEarlySyntacticErrors.baseline new file mode 100644 index 00000000000..a5d5d2eb9d7 --- /dev/null +++ b/tests/baselines/reference/getEmitOutputWithEarlySyntacticErrors.baseline @@ -0,0 +1,2 @@ +EmitOutputStatus : AllOutputGenerationSkipped + diff --git a/tests/baselines/reference/getEmitOutputWithSemanticErrorsForMultipleFiles.baseline b/tests/baselines/reference/getEmitOutputWithSemanticErrorsForMultipleFiles.baseline new file mode 100644 index 00000000000..c6396314824 --- /dev/null +++ b/tests/baselines/reference/getEmitOutputWithSemanticErrorsForMultipleFiles.baseline @@ -0,0 +1,8 @@ +EmitOutputStatus : Succeeded +Filename : tests/cases/fourslash/inputFile1.js +// File to emit, does not contain semantic errors +// expected to be emitted correctelly regardless of the semantic errors in the other file +var noErrors = true; +Filename : tests/cases/fourslash/inputFile1.d.ts +declare var noErrors: boolean; + diff --git a/tests/baselines/reference/getEmitOutputWithSemanticErrorsForMultipleFiles2.baseline b/tests/baselines/reference/getEmitOutputWithSemanticErrorsForMultipleFiles2.baseline new file mode 100644 index 00000000000..41b16b40e65 --- /dev/null +++ b/tests/baselines/reference/getEmitOutputWithSemanticErrorsForMultipleFiles2.baseline @@ -0,0 +1,8 @@ +EmitOutputStatus : DeclarationGenerationSkipped +Filename : out.js +// File to emit, does not contain semantic errors, but --out is passed +// expected to not generate declarations because of the semantic errors in the other file +var noErrors = true; +// File not emitted, and contains semantic errors +var semanticError = "string"; + diff --git a/tests/baselines/reference/getEmitOutputWithSyntacticErrorsForMultipleFiles.baseline b/tests/baselines/reference/getEmitOutputWithSyntacticErrorsForMultipleFiles.baseline new file mode 100644 index 00000000000..bf27703890b --- /dev/null +++ b/tests/baselines/reference/getEmitOutputWithSyntacticErrorsForMultipleFiles.baseline @@ -0,0 +1,6 @@ +EmitOutputStatus : Succeeded +Filename : tests/cases/fourslash/inputFile1.js +// File to emit, does not contain syntactic errors +// expected to be emitted correctelly regardless of the syntactic errors in the other file +var noErrors = true; + diff --git a/tests/baselines/reference/getEmitOutputWithSyntacticErrorsForMultipleFiles2.baseline b/tests/baselines/reference/getEmitOutputWithSyntacticErrorsForMultipleFiles2.baseline new file mode 100644 index 00000000000..a5d5d2eb9d7 --- /dev/null +++ b/tests/baselines/reference/getEmitOutputWithSyntacticErrorsForMultipleFiles2.baseline @@ -0,0 +1,2 @@ +EmitOutputStatus : AllOutputGenerationSkipped + diff --git a/tests/cases/fourslash/getEmitOutputWithEarlySemanticErrors.ts b/tests/cases/fourslash/getEmitOutputWithEarlySemanticErrors.ts new file mode 100644 index 00000000000..2946fffb808 --- /dev/null +++ b/tests/cases/fourslash/getEmitOutputWithEarlySemanticErrors.ts @@ -0,0 +1,10 @@ +/// + +// @BaselineFile: getEmitOutputWithEarlySyntacticErrors.baseline + +// @Filename: inputFile1.ts +// @emitThisFile: true +//// // File contains early errors. All outputs should be skipped. +//// const uninitialized_const_error; + +verify.baselineGetEmitOutput(); \ No newline at end of file diff --git a/tests/cases/fourslash/getEmitOutputWithSemanticErrorsForMultipleFiles.ts b/tests/cases/fourslash/getEmitOutputWithSemanticErrorsForMultipleFiles.ts new file mode 100644 index 00000000000..5cfacc36715 --- /dev/null +++ b/tests/cases/fourslash/getEmitOutputWithSemanticErrorsForMultipleFiles.ts @@ -0,0 +1,16 @@ +/// + +// @BaselineFile: getEmitOutputWithSemanticErrorsForMultipleFiles.baseline +// @declaration: true + +// @Filename: inputFile1.ts +// @emitThisFile: true +//// // File to emit, does not contain semantic errors +//// // expected to be emitted correctelly regardless of the semantic errors in the other file +//// var noErrors = true; + +// @Filename: inputFile2.ts +//// // File not emitted, and contains semantic errors +//// var semanticError: boolean = "string"; + +verify.baselineGetEmitOutput(); \ No newline at end of file diff --git a/tests/cases/fourslash/getEmitOutputWithSemanticErrorsForMultipleFiles2.ts b/tests/cases/fourslash/getEmitOutputWithSemanticErrorsForMultipleFiles2.ts new file mode 100644 index 00000000000..d5cfd1346ca --- /dev/null +++ b/tests/cases/fourslash/getEmitOutputWithSemanticErrorsForMultipleFiles2.ts @@ -0,0 +1,17 @@ +/// + +// @BaselineFile: getEmitOutputWithSemanticErrorsForMultipleFiles2.baseline +// @declaration: true +// @out: out.js + +// @Filename: inputFile1.ts +// @emitThisFile: true +//// // File to emit, does not contain semantic errors, but --out is passed +//// // expected to not generate declarations because of the semantic errors in the other file +//// var noErrors = true; + +// @Filename: inputFile2.ts +//// // File not emitted, and contains semantic errors +//// var semanticError: boolean = "string"; + +verify.baselineGetEmitOutput(); \ No newline at end of file diff --git a/tests/cases/fourslash/getEmitOutputWithSyntacticErrorsForMultipleFiles.ts b/tests/cases/fourslash/getEmitOutputWithSyntacticErrorsForMultipleFiles.ts new file mode 100644 index 00000000000..3b3d01eaac8 --- /dev/null +++ b/tests/cases/fourslash/getEmitOutputWithSyntacticErrorsForMultipleFiles.ts @@ -0,0 +1,15 @@ +/// + +// @BaselineFile: getEmitOutputWithSyntacticErrorsForMultipleFiles.baseline + +// @Filename: inputFile1.ts +// @emitThisFile: true +//// // File to emit, does not contain syntactic errors +//// // expected to be emitted correctelly regardless of the syntactic errors in the other file +//// var noErrors = true; + +// @Filename: inputFile2.ts +//// // File not emitted, and contains syntactic errors +//// var syntactic Error; + +verify.baselineGetEmitOutput(); \ No newline at end of file diff --git a/tests/cases/fourslash/getEmitOutputWithSyntacticErrorsForMultipleFiles2.ts b/tests/cases/fourslash/getEmitOutputWithSyntacticErrorsForMultipleFiles2.ts new file mode 100644 index 00000000000..ce82f958b91 --- /dev/null +++ b/tests/cases/fourslash/getEmitOutputWithSyntacticErrorsForMultipleFiles2.ts @@ -0,0 +1,16 @@ +/// + +// @BaselineFile: getEmitOutputWithSyntacticErrorsForMultipleFiles2.baseline +// @out: out.js + +// @Filename: inputFile1.ts +// @emitThisFile: true +//// // File to emit, does not contain syntactic errors, but --out is passed +//// // expected to not generate outputs because of the syntactic errors in the other file. +//// var noErrors = true; + +// @Filename: inputFile2.ts +//// // File not emitted, and contains syntactic errors +//// var syntactic Error; + +verify.baselineGetEmitOutput(); \ No newline at end of file From 03a2d0197bebac728f22f597e0f5c78a12331c48 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 23:17:34 -0800 Subject: [PATCH 28/41] Make 'CatchClause' have-a block, instead of be-a block. --- src/compiler/binder.ts | 10 ++--- src/compiler/checker.ts | 16 +++---- src/compiler/emitter.ts | 18 ++++---- src/compiler/parser.ts | 45 +++++++++---------- src/compiler/types.ts | 12 +++-- src/services/breakpoints.ts | 6 ++- src/services/formatting.ts | 6 +-- src/services/formatting/rules.ts | 5 +-- src/services/outliningElementsCollector.ts | 4 +- src/services/services.ts | 14 +++--- src/services/smartIndenter.ts | 4 +- .../sourceMapValidationStatements.js.map | 2 +- ...ourceMapValidationStatements.sourcemap.txt | 20 ++++----- .../sourceMapValidationTryCatchFinally.js.map | 2 +- ...MapValidationTryCatchFinally.sourcemap.txt | 22 ++++----- 15 files changed, 94 insertions(+), 92 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 469a794d13d..a45561e7ed6 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -348,8 +348,8 @@ module ts { bindChildren(node, symbolKind, isBlockScopeContainer); } - function bindCatchVariableDeclaration(node: CatchBlock) { - var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.variable.text || "__missing"); + function bindCatchVariableDeclaration(node: CatchClause) { + var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.name.text || "__missing"); addDeclarationToSymbol(symbol, node, SymbolFlags.FunctionScopedVariable); var saveParent = parent; var savedBlockScopeContainer = blockScopeContainer; @@ -444,8 +444,8 @@ module ts { case SyntaxKind.ArrowFunction: bindAnonymousDeclaration(node, SymbolFlags.Function, "__function", /*isBlockScopeContainer*/ true); break; - case SyntaxKind.CatchBlock: - bindCatchVariableDeclaration(node); + case SyntaxKind.CatchClause: + bindCatchVariableDeclaration(node); break; case SyntaxKind.ClassDeclaration: bindDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes, /*isBlockScopeContainer*/ false); @@ -478,7 +478,7 @@ module ts { case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: case SyntaxKind.ForStatement: case SyntaxKind.ForInStatement: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 64ed5f25bca..c6c58347b19 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -415,8 +415,8 @@ module ts { break loop; } break; - case SyntaxKind.CatchBlock: - var id = (location).variable; + case SyntaxKind.CatchClause: + var id = (location).name; if (name === id.text) { result = location.symbol; break loop; @@ -1753,7 +1753,7 @@ module ts { } // Handle catch clause variables var declaration = symbol.valueDeclaration; - if (declaration.kind === SyntaxKind.CatchBlock) { + if (declaration.kind === SyntaxKind.CatchClause) { return links.type = anyType; } // Handle variable, parameter or property @@ -4375,7 +4375,7 @@ module ts { case SyntaxKind.ThrowStatement: case SyntaxKind.TryStatement: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: return forEachChild(node, isAssignedIn); } @@ -7767,7 +7767,7 @@ module ts { function checkTryStatement(node: TryStatement) { checkBlock(node.tryBlock); - if (node.catchBlock) checkBlock(node.catchBlock); + if (node.catchClause) checkBlock(node.catchClause.block); if (node.finallyBlock) checkBlock(node.finallyBlock); } @@ -8605,7 +8605,7 @@ module ts { case SyntaxKind.ThrowStatement: case SyntaxKind.TryStatement: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: case SyntaxKind.VariableDeclaration: case SyntaxKind.ClassDeclaration: @@ -8767,8 +8767,8 @@ module ts { copySymbol(location.symbol, meaning); } break; - case SyntaxKind.CatchBlock: - if ((location).variable.text) { + case SyntaxKind.CatchClause: + if ((location).name.text) { copySymbol(location.symbol, meaning); } break; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b065287b7d2..53914ac4c62 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2142,8 +2142,8 @@ module ts { return false; case SyntaxKind.LabeledStatement: return (node.parent).label === node; - case SyntaxKind.CatchBlock: - return (node.parent).variable === node; + case SyntaxKind.CatchClause: + return (node.parent).name === node; } } @@ -2650,7 +2650,7 @@ module ts { function emitTryStatement(node: TryStatement) { write("try "); emit(node.tryBlock); - emit(node.catchBlock); + emit(node.catchClause); if (node.finallyBlock) { writeLine(); write("finally "); @@ -2658,15 +2658,15 @@ module ts { } } - function emitCatchBlock(node: CatchBlock) { + function emitCatchClause(node: CatchClause) { writeLine(); var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos); write(" "); emitToken(SyntaxKind.OpenParenToken, endPos); - emit(node.variable); - emitToken(SyntaxKind.CloseParenToken, node.variable.end); + emit(node.name); + emitToken(SyntaxKind.CloseParenToken, node.name.end); write(" "); - emitBlock(node); + emitBlock(node.block); } function emitDebuggerStatement(node: Node) { @@ -3599,8 +3599,8 @@ module ts { return emitThrowStatement(node); case SyntaxKind.TryStatement: return emitTryStatement(node); - case SyntaxKind.CatchBlock: - return emitCatchBlock(node); + case SyntaxKind.CatchClause: + return emitCatchClause(node); case SyntaxKind.DebuggerStatement: return emitDebuggerStatement(node); case SyntaxKind.VariableDeclaration: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a45de6309d4..553d51b1bd2 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -364,11 +364,12 @@ module ts { return child((node).expression); case SyntaxKind.TryStatement: return child((node).tryBlock) || - child((node).catchBlock) || + child((node).catchClause) || child((node).finallyBlock); - case SyntaxKind.CatchBlock: - return child((node).variable) || - children((node).statements); + case SyntaxKind.CatchClause: + return child((node).name) || + child((node).type) || + child((node).block); case SyntaxKind.VariableDeclaration: return children(node.modifiers) || child((node).name) || @@ -445,7 +446,7 @@ module ts { case SyntaxKind.LabeledStatement: case SyntaxKind.TryStatement: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: return forEachChild(node, traverse); } @@ -733,8 +734,8 @@ module ts { return (parent).name === name; } - if (parent.kind === SyntaxKind.CatchBlock) { - return (parent).variable === name; + if (parent.kind === SyntaxKind.CatchClause) { + return (parent).name === name; } return false; @@ -3439,11 +3440,11 @@ module ts { function parseTryStatement(): TryStatement { var node = createNode(SyntaxKind.TryStatement); node.tryBlock = parseTokenAndBlock(SyntaxKind.TryKeyword); - node.catchBlock = token === SyntaxKind.CatchKeyword ? parseCatchBlock() : undefined; + node.catchClause = token === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined; // If we don't have a catch clause, then we must have a finally clause. Try to parse // one out no matter what. - node.finallyBlock = !node.catchBlock || token === SyntaxKind.FinallyKeyword + node.finallyBlock = !node.catchClause || token === SyntaxKind.FinallyKeyword ? parseTokenAndBlock(SyntaxKind.FinallyKeyword) : undefined; return finishNode(node); @@ -3459,19 +3460,15 @@ module ts { return result; } - function parseCatchBlock(): CatchBlock { - var pos = getNodePos(); + function parseCatchClause(): CatchClause { + var result = createNode(SyntaxKind.CatchClause); parseExpected(SyntaxKind.CatchKeyword); parseExpected(SyntaxKind.OpenParenToken); - var variable = parseIdentifier(); - var typeAnnotation = parseTypeAnnotation(); + result.name = parseIdentifier(); + result.type = parseTypeAnnotation(); parseExpected(SyntaxKind.CloseParenToken); - var result = parseBlock(SyntaxKind.CatchBlock, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false); - result.pos = pos; - result.variable = variable; - result.type = typeAnnotation; - - return result; + result.block = parseBlock(SyntaxKind.Block, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false); + return finishNode(result); } function parseDebuggerStatement(): Statement { @@ -4325,7 +4322,7 @@ module ts { case SyntaxKind.EnumDeclaration: return checkEnumDeclaration(node); case SyntaxKind.BinaryExpression: return checkBinaryExpression(node); - case SyntaxKind.CatchBlock: return checkCatchBlock(node); + case SyntaxKind.CatchClause: return checkCatchClause(node); case SyntaxKind.ClassDeclaration: return checkClassDeclaration(node); case SyntaxKind.ComputedPropertyName: return checkComputedPropertyName(node); case SyntaxKind.Constructor: return checkConstructor(node); @@ -4583,15 +4580,15 @@ module ts { } } - function checkCatchBlock(node: CatchBlock) { + function checkCatchClause(node: CatchClause) { if (node.type) { - var colonStart = skipTrivia(sourceText, node.variable.end); + var colonStart = skipTrivia(sourceText, node.name.end); return grammarErrorAtPos(colonStart, ":".length, Diagnostics.Catch_clause_parameter_cannot_have_a_type_annotation); } - if (node.parserContextFlags & ParserContextFlags.StrictMode && isEvalOrArgumentsIdentifier(node.variable)) { + if (node.parserContextFlags & ParserContextFlags.StrictMode && isEvalOrArgumentsIdentifier(node.name)) { // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the // Catch production is eval or arguments - return reportInvalidUseInStrictMode(node.variable); + return reportInvalidUseInStrictMode(node.name); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a042ceae14d..d8cbf204ebc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -208,7 +208,6 @@ module ts { ThrowStatement, TryStatement, TryBlock, - CatchBlock, FinallyBlock, DebuggerStatement, VariableDeclaration, @@ -222,12 +221,16 @@ module ts { ModuleBlock, ImportDeclaration, ExportAssignment, + // Module references ExternalModuleReference, + // Clauses CaseClause, DefaultClause, HeritageClause, + CatchClause, + // Property assignments PropertyAssignment, ShorthandPropertyAssignment, @@ -693,13 +696,14 @@ module ts { export interface TryStatement extends Statement { tryBlock: Block; - catchBlock?: CatchBlock; + catchClause?: CatchClause; finallyBlock?: Block; } - export interface CatchBlock extends Block, Declaration { - variable: Identifier; + export interface CatchClause extends Declaration { + name: Identifier; type?: TypeNode; + block: Block; } export interface ModuleElement extends Node { diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index eb9c88088aa..a67a89dd82f 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -106,11 +106,13 @@ module ts.BreakpointResolver { case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: return spanInBlock(node); + case SyntaxKind.CatchClause: + return spanInBlock((node).block); + case SyntaxKind.ExpressionStatement: // span on the expression return textSpan((node).expression); @@ -420,7 +422,7 @@ module ts.BreakpointResolver { case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: return spanInNode((node.parent).statements[(node.parent).statements.length - 1]);; diff --git a/src/services/formatting.ts b/src/services/formatting.ts index 741b853b7ba..3322ea1e65b 100644 --- a/src/services/formatting.ts +++ b/src/services/formatting.ts @@ -155,10 +155,11 @@ module ts.formatting { case SyntaxKind.SourceFile: case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: - return rangeContainsRange((parent).statements, node) + return rangeContainsRange((parent).statements, node); + case SyntaxKind.CatchClause: + return rangeContainsRange((parent).block.statements, node); } return false; @@ -898,7 +899,6 @@ module ts.formatting { case SyntaxKind.Block: case SyntaxKind.FunctionBlock: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: return true; diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 7de7baee6ca..2723b50af7b 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -525,7 +525,6 @@ module ts.formatting { case SyntaxKind.SwitchStatement: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: @@ -581,7 +580,7 @@ module ts.formatting { case SyntaxKind.EnumDeclaration: case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: @@ -603,7 +602,7 @@ module ts.formatting { case SyntaxKind.WithStatement: // TODO // case SyntaxKind.ElseClause: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: return true; diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 7f071e5c224..68f30bee781 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -79,7 +79,8 @@ module ts { parent.kind === SyntaxKind.ForStatement || parent.kind === SyntaxKind.IfStatement || parent.kind === SyntaxKind.WhileStatement || - parent.kind === SyntaxKind.WithStatement) { + parent.kind === SyntaxKind.WithStatement || + parent.kind === SyntaxKind.CatchClause) { addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n)); } @@ -100,7 +101,6 @@ module ts { case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); diff --git a/src/services/services.ts b/src/services/services.ts index 7e9e84cd7af..b20067887b3 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2576,7 +2576,7 @@ module ts { isFunction(containingNodeKind); case SyntaxKind.OpenParenToken: - return containingNodeKind === SyntaxKind.CatchBlock || + return containingNodeKind === SyntaxKind.CatchClause || isFunction(containingNodeKind); case SyntaxKind.OpenBraceToken: @@ -3567,8 +3567,8 @@ module ts { else if (node.kind === SyntaxKind.TryStatement) { var tryStatement = node; - if (tryStatement.catchBlock) { - aggregate(tryStatement.catchBlock); + if (tryStatement.catchClause) { + aggregate(tryStatement.catchClause); } else { // Exceptions thrown within a try block lacking a catch clause @@ -3607,7 +3607,7 @@ module ts { if (parent.kind === SyntaxKind.TryStatement) { var tryStatement = parent; - if (tryStatement.tryBlock === child && tryStatement.catchBlock) { + if (tryStatement.tryBlock === child && tryStatement.catchClause) { return child; } } @@ -3623,8 +3623,8 @@ module ts { pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); - if (tryStatement.catchBlock) { - pushKeywordIf(keywords, tryStatement.catchBlock.getFirstToken(), SyntaxKind.CatchKeyword); + if (tryStatement.catchClause) { + pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), SyntaxKind.CatchKeyword); } if (tryStatement.finallyBlock) { @@ -4738,7 +4738,7 @@ module ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: return SemanticMeaning.Value; case SyntaxKind.TypeParameter: diff --git a/src/services/smartIndenter.ts b/src/services/smartIndenter.ts index 4e32522040e..82226449b96 100644 --- a/src/services/smartIndenter.ts +++ b/src/services/smartIndenter.ts @@ -328,7 +328,6 @@ module ts.formatting { case SyntaxKind.Block: case SyntaxKind.FunctionBlock: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.ObjectLiteralExpression: @@ -404,12 +403,13 @@ module ts.formatting { case SyntaxKind.EnumDeclaration: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.Block: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.SwitchStatement: return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile); + case SyntaxKind.CatchClause: + return isCompletedNode((n).block, sourceFile); case SyntaxKind.ParenthesizedExpression: case SyntaxKind.CallSignature: case SyntaxKind.CallExpression: diff --git a/tests/baselines/reference/sourceMapValidationStatements.js.map b/tests/baselines/reference/sourceMapValidationStatements.js.map index 02b5c0bb806..8eb99944914 100644 --- a/tests/baselines/reference/sourceMapValidationStatements.js.map +++ b/tests/baselines/reference/sourceMapValidationStatements.js.map @@ -1,2 +1,2 @@ //// [sourceMapValidationStatements.js.map] -{"version":3,"file":"sourceMapValidationStatements.js","sourceRoot":"","sources":["sourceMapValidationStatements.ts"],"names":["f"],"mappings":"AAAA,SAAS,CAAC;IACNA,IAAIA,CAACA,CAACA;IACNA,IAAIA,CAACA,GAAGA,CAACA,CAACA;IACVA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,CAACA,GAAGA,EAAEA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;QAC1BA,CAACA,IAAIA,CAACA,CAACA;QACPA,CAACA,IAAIA,CAACA,CAACA;IACXA,CAACA;IACDA,EAAEA,CAACA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;QACTA,CAACA,IAAIA,CAACA,CAACA;IACXA,CAACA;IAACA,IAAIA,CAACA,CAACA;QACJA,CAACA,IAAIA,EAAEA,CAACA;QACRA,CAACA,EAAEA,CAACA;IACRA,CAACA;IACDA,IAAIA,CAACA,GAAGA;QACJA,CAACA;QACDA,CAACA;QACDA,CAACA;KACJA,CAACA;IACFA,IAAIA,GAAGA,GAAGA;QACNA,CAACA,EAAEA,CAACA;QACJA,CAACA,EAAEA,OAAOA;KACbA,CAACA;IACFA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA;QACdA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,CAACA;QACbA,IAAIA,CAACA,GAAGA,EAAEA,CAACA;IACfA,CAACA;IACDA,IAAAA,CAACA;QACGA,GAAGA,CAACA,CAACA,GAAGA,MAAMA,CAACA;IACnBA,CAAEA;IAAAA,KAAKA,CAACA,CAACA,CAACA,CAACA,CAATA,CAACA;QACCA,EAAEA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;YACbA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,CAACA;QACfA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACJA,GAAGA,CAACA,CAACA,GAAGA,KAAKA,CAACA;QAClBA,CAACA;IACLA,CAACA;IACDA,IAAAA,CAACA;QACGA,MAAMA,IAAIA,KAAKA,EAAEA,CAACA;IACtBA,CAAEA;IAAAA,KAAKA,CAACA,CAACA,EAAEA,CAACA,CAAVA,CAACA;QACCA,IAAIA,CAACA,GAAGA,EAAEA,CAACA;IACfA,CAACA;YAACA,CAACA;QACCA,CAACA,GAAGA,EAAEA,CAACA;IACXA,CAACA;IACDA,MAAMA,GAAGA,EAAEA,CAACA;QACRA,CAACA,GAAGA,CAACA,CAACA;QACNA,CAACA,GAAGA,EAAEA,CAACA;IACXA,CAACA;IACDA,MAAMA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,CAACA;QACZA,KAAKA,CAACA,EAAEA,CAACA;YACLA,CAACA,EAAEA,CAACA;YACJA,KAAKA,CAACA;QAEVA,CAACA;QACDA,KAAKA,CAACA,EAAEA,CAACA;YACLA,CAACA,EAAEA,CAACA;YACJA,KAAKA,CAACA;QAEVA,CAACA;QACDA,SAASA,CAACA;YACNA,CAACA,IAAIA,CAACA,CAACA;YACPA,CAACA,GAAGA,EAAEA,CAACA;YACPA,KAAKA,CAACA;QAEVA,CAACA;IACLA,CAACA;IACDA,OAAOA,CAACA,GAAGA,EAAEA,EAAEA,CAACA;QACZA,CAACA,EAAEA,CAACA;IACRA,CAACA;IACDA,GAAGA,CAACA;QACAA,CAACA,EAAEA,CAACA;IACRA,CAACA,QAAQA,CAACA,GAAGA,CAACA,EAACA;IACfA,CAACA,GAAGA,CAACA,CAACA;IACNA,IAAIA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;IACjCA,CAACA,CAACA,IAAIA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;IACzBA,CAACA,KAAKA,CAACA,CAACA;IACRA,CAACA,GAAGA,CAACA,GAAGA,EAAEA,CAACA;IACXA,IAAIA,CAACA,GAAGA,CAACA,CAACA;IACVA,MAAMA,CAACA;AACXA,CAACA;AACD,IAAI,CAAC,GAAG;IACJ,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC,CAAC;AACF,CAAC,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"sourceMapValidationStatements.js","sourceRoot":"","sources":["sourceMapValidationStatements.ts"],"names":["f"],"mappings":"AAAA,SAAS,CAAC;IACNA,IAAIA,CAACA,CAACA;IACNA,IAAIA,CAACA,GAAGA,CAACA,CAACA;IACVA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,CAACA,GAAGA,EAAEA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;QAC1BA,CAACA,IAAIA,CAACA,CAACA;QACPA,CAACA,IAAIA,CAACA,CAACA;IACXA,CAACA;IACDA,EAAEA,CAACA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;QACTA,CAACA,IAAIA,CAACA,CAACA;IACXA,CAACA;IAACA,IAAIA,CAACA,CAACA;QACJA,CAACA,IAAIA,EAAEA,CAACA;QACRA,CAACA,EAAEA,CAACA;IACRA,CAACA;IACDA,IAAIA,CAACA,GAAGA;QACJA,CAACA;QACDA,CAACA;QACDA,CAACA;KACJA,CAACA;IACFA,IAAIA,GAAGA,GAAGA;QACNA,CAACA,EAAEA,CAACA;QACJA,CAACA,EAAEA,OAAOA;KACbA,CAACA;IACFA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA;QACdA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,CAACA;QACbA,IAAIA,CAACA,GAAGA,EAAEA,CAACA;IACfA,CAACA;IACDA,IAAAA,CAACA;QACGA,GAAGA,CAACA,CAACA,GAAGA,MAAMA,CAACA;IACnBA,CAAEA;IAAAA,KAAKA,CAACA,CAACA,CAACA,CAACA,CAACA,CAACA;QACTA,EAAEA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;YACbA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,CAACA;QACfA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACJA,GAAGA,CAACA,CAACA,GAAGA,KAAKA,CAACA;QAClBA,CAACA;IACLA,CAACA;IACDA,IAAAA,CAACA;QACGA,MAAMA,IAAIA,KAAKA,EAAEA,CAACA;IACtBA,CAAEA;IAAAA,KAAKA,CAACA,CAACA,EAAEA,CAACA,CAACA,CAACA;QACVA,IAAIA,CAACA,GAAGA,EAAEA,CAACA;IACfA,CAACA;YAACA,CAACA;QACCA,CAACA,GAAGA,EAAEA,CAACA;IACXA,CAACA;IACDA,MAAMA,GAAGA,EAAEA,CAACA;QACRA,CAACA,GAAGA,CAACA,CAACA;QACNA,CAACA,GAAGA,EAAEA,CAACA;IACXA,CAACA;IACDA,MAAMA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,CAACA;QACZA,KAAKA,CAACA,EAAEA,CAACA;YACLA,CAACA,EAAEA,CAACA;YACJA,KAAKA,CAACA;QAEVA,CAACA;QACDA,KAAKA,CAACA,EAAEA,CAACA;YACLA,CAACA,EAAEA,CAACA;YACJA,KAAKA,CAACA;QAEVA,CAACA;QACDA,SAASA,CAACA;YACNA,CAACA,IAAIA,CAACA,CAACA;YACPA,CAACA,GAAGA,EAAEA,CAACA;YACPA,KAAKA,CAACA;QAEVA,CAACA;IACLA,CAACA;IACDA,OAAOA,CAACA,GAAGA,EAAEA,EAAEA,CAACA;QACZA,CAACA,EAAEA,CAACA;IACRA,CAACA;IACDA,GAAGA,CAACA;QACAA,CAACA,EAAEA,CAACA;IACRA,CAACA,QAAQA,CAACA,GAAGA,CAACA,EAACA;IACfA,CAACA,GAAGA,CAACA,CAACA;IACNA,IAAIA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;IACjCA,CAACA,CAACA,IAAIA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;IACzBA,CAACA,KAAKA,CAACA,CAACA;IACRA,CAACA,GAAGA,CAACA,GAAGA,EAAEA,CAACA;IACXA,IAAIA,CAACA,GAAGA,CAACA,CAACA;IACVA,MAAMA,CAACA;AACXA,CAACA;AACD,IAAI,CAAC,GAAG;IACJ,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC,CAAC;AACF,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationStatements.sourcemap.txt b/tests/baselines/reference/sourceMapValidationStatements.sourcemap.txt index 1a288e3a830..ef7aef275c0 100644 --- a/tests/baselines/reference/sourceMapValidationStatements.sourcemap.txt +++ b/tests/baselines/reference/sourceMapValidationStatements.sourcemap.txt @@ -557,16 +557,16 @@ sourceFile:sourceMapValidationStatements.ts 4 > ( 5 > e 6 > ) -7 > -8 > c +7 > +8 > { 1->Emitted(31, 5) Source(29, 7) + SourceIndex(0) name (f) 2 >Emitted(31, 10) Source(29, 12) + SourceIndex(0) name (f) 3 >Emitted(31, 11) Source(29, 13) + SourceIndex(0) name (f) 4 >Emitted(31, 12) Source(29, 14) + SourceIndex(0) name (f) 5 >Emitted(31, 13) Source(29, 15) + SourceIndex(0) name (f) 6 >Emitted(31, 14) Source(29, 16) + SourceIndex(0) name (f) -7 >Emitted(31, 15) Source(29, 7) + SourceIndex(0) name (f) -8 >Emitted(31, 16) Source(29, 8) + SourceIndex(0) name (f) +7 >Emitted(31, 15) Source(29, 17) + SourceIndex(0) name (f) +8 >Emitted(31, 16) Source(29, 18) + SourceIndex(0) name (f) --- >>> if (obj.z < 10) { 1->^^^^^^^^ @@ -581,7 +581,7 @@ sourceFile:sourceMapValidationStatements.ts 10> ^ 11> ^ 12> ^ -1->atch (e) { +1-> > 2 > if 3 > @@ -759,16 +759,16 @@ sourceFile:sourceMapValidationStatements.ts 4 > ( 5 > e1 6 > ) -7 > -8 > c +7 > +8 > { 1->Emitted(42, 5) Source(38, 7) + SourceIndex(0) name (f) 2 >Emitted(42, 10) Source(38, 12) + SourceIndex(0) name (f) 3 >Emitted(42, 11) Source(38, 13) + SourceIndex(0) name (f) 4 >Emitted(42, 12) Source(38, 14) + SourceIndex(0) name (f) 5 >Emitted(42, 14) Source(38, 16) + SourceIndex(0) name (f) 6 >Emitted(42, 15) Source(38, 17) + SourceIndex(0) name (f) -7 >Emitted(42, 16) Source(38, 7) + SourceIndex(0) name (f) -8 >Emitted(42, 17) Source(38, 8) + SourceIndex(0) name (f) +7 >Emitted(42, 16) Source(38, 18) + SourceIndex(0) name (f) +8 >Emitted(42, 17) Source(38, 19) + SourceIndex(0) name (f) --- >>> var b = e1; 1->^^^^^^^^ @@ -777,7 +777,7 @@ sourceFile:sourceMapValidationStatements.ts 4 > ^^^ 5 > ^^ 6 > ^ -1->atch (e1) { +1-> > 2 > var 3 > b diff --git a/tests/baselines/reference/sourceMapValidationTryCatchFinally.js.map b/tests/baselines/reference/sourceMapValidationTryCatchFinally.js.map index 24b7b84a3d0..89716807538 100644 --- a/tests/baselines/reference/sourceMapValidationTryCatchFinally.js.map +++ b/tests/baselines/reference/sourceMapValidationTryCatchFinally.js.map @@ -1,2 +1,2 @@ //// [sourceMapValidationTryCatchFinally.js.map] -{"version":3,"file":"sourceMapValidationTryCatchFinally.js","sourceRoot":"","sources":["sourceMapValidationTryCatchFinally.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,EAAE,CAAC;AACX,IAAA,CAAC;IACG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAE;AAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CAAT,CAAC;IACC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;QAAC,CAAC;IACC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AACf,CAAC;AACD,IAAA,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,IAAI,KAAK,EAAE,CAAC;AACtB,CACA;AAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CAAT,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;QACD,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AACf,CAAC"} \ No newline at end of file +{"version":3,"file":"sourceMapValidationTryCatchFinally.js","sourceRoot":"","sources":["sourceMapValidationTryCatchFinally.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,EAAE,CAAC;AACX,IAAA,CAAC;IACG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAE;AAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACT,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;QAAC,CAAC;IACC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AACf,CAAC;AACD,IAAA,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,IAAI,KAAK,EAAE,CAAC;AACtB,CACA;AAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CACT,CAAC;IACG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;QACD,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AACf,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationTryCatchFinally.sourcemap.txt b/tests/baselines/reference/sourceMapValidationTryCatchFinally.sourcemap.txt index aa0b846ece8..25dee4fbc45 100644 --- a/tests/baselines/reference/sourceMapValidationTryCatchFinally.sourcemap.txt +++ b/tests/baselines/reference/sourceMapValidationTryCatchFinally.sourcemap.txt @@ -91,16 +91,16 @@ sourceFile:sourceMapValidationTryCatchFinally.ts 4 > ( 5 > e 6 > ) -7 > -8 > c +7 > +8 > { 1->Emitted(5, 1) Source(4, 3) + SourceIndex(0) 2 >Emitted(5, 6) Source(4, 8) + SourceIndex(0) 3 >Emitted(5, 7) Source(4, 9) + SourceIndex(0) 4 >Emitted(5, 8) Source(4, 10) + SourceIndex(0) 5 >Emitted(5, 9) Source(4, 11) + SourceIndex(0) 6 >Emitted(5, 10) Source(4, 12) + SourceIndex(0) -7 >Emitted(5, 11) Source(4, 3) + SourceIndex(0) -8 >Emitted(5, 12) Source(4, 4) + SourceIndex(0) +7 >Emitted(5, 11) Source(4, 13) + SourceIndex(0) +8 >Emitted(5, 12) Source(4, 14) + SourceIndex(0) --- >>> x = x - 1; 1->^^^^ @@ -110,7 +110,7 @@ sourceFile:sourceMapValidationTryCatchFinally.ts 5 > ^^^ 6 > ^ 7 > ^ -1->atch (e) { +1-> > 2 > x 3 > = @@ -266,16 +266,17 @@ sourceFile:sourceMapValidationTryCatchFinally.ts 4 > ( 5 > e 6 > ) -7 > -8 > c +7 > + > +8 > { 1->Emitted(15, 1) Source(14, 1) + SourceIndex(0) 2 >Emitted(15, 6) Source(14, 6) + SourceIndex(0) 3 >Emitted(15, 7) Source(14, 7) + SourceIndex(0) 4 >Emitted(15, 8) Source(14, 8) + SourceIndex(0) 5 >Emitted(15, 9) Source(14, 9) + SourceIndex(0) 6 >Emitted(15, 10) Source(14, 10) + SourceIndex(0) -7 >Emitted(15, 11) Source(14, 1) + SourceIndex(0) -8 >Emitted(15, 12) Source(14, 2) + SourceIndex(0) +7 >Emitted(15, 11) Source(15, 1) + SourceIndex(0) +8 >Emitted(15, 12) Source(15, 2) + SourceIndex(0) --- >>> x = x - 1; 1->^^^^ @@ -285,8 +286,7 @@ sourceFile:sourceMapValidationTryCatchFinally.ts 5 > ^^^ 6 > ^ 7 > ^ -1->atch (e) - >{ +1-> > 2 > x 3 > = From 581ef9f2b093ec51a28d2c31a4da654dc5df25ec Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 23:39:44 -0800 Subject: [PATCH 29/41] Remove arrow allocations from the parser in a few places. --- src/compiler/parser.ts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 553d51b1bd2..4198ad50221 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3551,7 +3551,7 @@ module ts { case SyntaxKind.StaticKeyword: // When followed by an identifier or keyword, these do not start a statement but // might instead be following type members - if (lookAhead(() => nextToken() >= SyntaxKind.Identifier)) { + if (lookAhead(() => nextToken() >= SyntaxKind.Identifier && !scanner.hasPrecedingLineBreak())) { return false; } default: @@ -3702,12 +3702,16 @@ module ts { property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); - property.initializer = allowInAnd(() => parseInitializer(/*inParameter*/ false)); + property.initializer = allowInAnd(parseNonParameterInitializer); parseSemicolon(); return finishNode(property); } } + function parseNonParameterInitializer() { + return parseInitializer(/*inParameter*/ false); + } + function parseMemberAccessorDeclaration(kind: SyntaxKind, fullStart: number, modifiers: ModifiersArray): MethodDeclaration { var node = createNode(kind, fullStart); setModifiers(node, modifiers); @@ -3913,11 +3917,11 @@ module ts { function parseEnumMember(): EnumMember { var node = createNode(SyntaxKind.EnumMember, scanner.getStartPos()); node.name = parsePropertyName(); - node.initializer = allowInAnd(() => parseInitializer(/*inParameter*/ false)); + node.initializer = allowInAnd(parseNonParameterInitializer); return finishNode(node); } - function parseAndCheckEnumDeclaration(fullStart: number, modifiers: ModifiersArray, flags: NodeFlags): EnumDeclaration { + function parseEnumDeclaration(fullStart: number, modifiers: ModifiersArray): EnumDeclaration { var node = createNode(SyntaxKind.EnumDeclaration, fullStart); setModifiers(node, modifiers); parseExpected(SyntaxKind.EnumKeyword); @@ -3935,7 +3939,7 @@ module ts { function parseModuleBlock(): ModuleBlock { var node = createNode(SyntaxKind.ModuleBlock, scanner.getStartPos()); if (parseExpected(SyntaxKind.OpenBraceToken)) { - node.statements = parseList(ParsingContext.ModuleElements, /*checkForStrictMode*/ false, parseModuleElement); + node.statements = parseList(ParsingContext.ModuleElements, /*checkForStrictMode*/false, parseModuleElement); parseExpected(SyntaxKind.CloseBraceToken); } else { @@ -3955,20 +3959,19 @@ module ts { return finishNode(node); } - function parseAmbientExternalModuleDeclaration(fullStart: number, modifiers: ModifiersArray, flags: NodeFlags): ModuleDeclaration { + function parseAmbientExternalModuleDeclaration(fullStart: number, modifiers: ModifiersArray): ModuleDeclaration { var node = createNode(SyntaxKind.ModuleDeclaration, fullStart); setModifiers(node, modifiers); - node.flags |= flags; node.name = parseLiteralNode(/*internName:*/ true); node.body = parseModuleBlock(); return finishNode(node); } - function parseModuleDeclaration(fullStart: number, modifiers: ModifiersArray, flags: NodeFlags): ModuleDeclaration { + function parseModuleDeclaration(fullStart: number, modifiers: ModifiersArray): ModuleDeclaration { parseExpected(SyntaxKind.ModuleKeyword); return token === SyntaxKind.StringLiteral - ? parseAmbientExternalModuleDeclaration(fullStart, modifiers, flags) - : parseInternalModuleTail(fullStart, modifiers, flags); + ? parseAmbientExternalModuleDeclaration(fullStart, modifiers) + : parseInternalModuleTail(fullStart, modifiers, modifiers? modifiers.flags : 0); } function isExternalModuleReference() { @@ -4063,7 +4066,6 @@ module ts { } } - var flags = modifiers ? modifiers.flags : 0; switch (token) { case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: @@ -4078,9 +4080,9 @@ module ts { case SyntaxKind.TypeKeyword: return parseTypeAliasDeclaration(fullStart, modifiers); case SyntaxKind.EnumKeyword: - return parseAndCheckEnumDeclaration(fullStart, modifiers, flags); + return parseEnumDeclaration(fullStart, modifiers); case SyntaxKind.ModuleKeyword: - return parseModuleDeclaration(fullStart, modifiers, flags); + return parseModuleDeclaration(fullStart, modifiers); case SyntaxKind.ImportKeyword: return parseImportDeclaration(fullStart, modifiers); default: From deca94427c0f160899e4e9bc14ee89fe46f427d6 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Dec 2014 00:02:15 -0800 Subject: [PATCH 30/41] Reduce arrow function allocations in the parser. --- src/compiler/parser.ts | 411 ++++++++++++++++++++++++----------------- 1 file changed, 245 insertions(+), 166 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4198ad50221..9397661839d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1347,11 +1347,11 @@ module ts { } function parseIdentifierName(): Identifier { - return createIdentifier(token >= SyntaxKind.Identifier); + return createIdentifier(isIdentifierOrKeyword()); } function isLiteralPropertyName(): boolean { - return token >= SyntaxKind.Identifier || + return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral; } @@ -1439,7 +1439,9 @@ module ts { case ParsingContext.ObjectLiteralMembers: return token === SyntaxKind.OpenBracketToken || token === SyntaxKind.AsteriskToken || isLiteralPropertyName(); case ParsingContext.TypeReferences: - return isIdentifier() && ((token !== SyntaxKind.ExtendsKeyword && token !== SyntaxKind.ImplementsKeyword) || !lookAhead(() => (nextToken(), isIdentifier()))); + // We want to make sure that the "extends" in "extends foo" or the "implements" in + // "implements foo" is not considered a type name. + return isIdentifier() && !isNotHeritageClauseTypeName(); case ParsingContext.VariableDeclarations: case ParsingContext.TypeParameters: return isIdentifier(); @@ -1459,6 +1461,21 @@ module ts { Debug.fail("Non-exhaustive case in 'isListElement'."); } + function nextTokenIsIdentifier() { + nextToken(); + return isIdentifier(); + } + + function isNotHeritageClauseTypeName(): boolean { + if (token === SyntaxKind.ImplementsKeyword || + token === SyntaxKind.ExtendsKeyword) { + + return lookAhead(nextTokenIsIdentifier); + } + + return false; + } + // True if positioned at a list terminator function isListTerminator(kind: ParsingContext): boolean { if (token === SyntaxKind.EndOfFileToken) { @@ -1689,10 +1706,7 @@ module ts { // In the first case though, ASI will not take effect because there is not a // line terminator after the keyword. if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord()) { - var matchesPattern = lookAhead(() => { - nextToken(); - return !scanner.hasPrecedingLineBreak() && (scanner.isIdentifier() || scanner.isReservedWord()); - }); + var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); if (matchesPattern) { // Report that we need an identifier. However, report it right after the dot, @@ -1705,6 +1719,8 @@ module ts { return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } + + function parseTokenNode(): T { var node = createNode(token); nextToken(); @@ -1972,58 +1988,62 @@ module ts { return false; } - return lookAhead(() => { - // The only allowed sequence is: - // - // [id: - // - // However, for error recovery, we also check the following cases: - // - // [... - // [id, - // [id?, - // [id?: - // [id?] - // [public id - // [private id - // [protected id - // [] - // - if (nextToken() === SyntaxKind.DotDotDotToken || token === SyntaxKind.CloseBracketToken) { + return lookAhead(isUnambiguouslyIndexSignature); + } + + function isUnambiguouslyIndexSignature() { + // The only allowed sequence is: + // + // [id: + // + // However, for error recovery, we also check the following cases: + // + // [... + // [id, + // [id?, + // [id?: + // [id?] + // [public id + // [private id + // [protected id + // [] + // + nextToken(); + if (token === SyntaxKind.DotDotDotToken || token === SyntaxKind.CloseBracketToken) { + return true; + } + + if (isModifier(token)) { + nextToken(); + if (isIdentifier()) { return true; } + } + else if (!isIdentifier()) { + return false; + } + else { + // Skip the identifier + nextToken(); + } - if (isModifier(token)) { - nextToken(); - if (isIdentifier()) { - return true; - } - } - else if (!isIdentifier()) { - return false; - } - else { - // Skip the identifier - nextToken(); - } + // A colon signifies a well formed indexer + // A comma should be a badly formed indexer because comma expressions are not allowed + // in computed properties. + if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken) { + return true; + } - // A colon signifies a well formed indexer - // A comma should be a badly formed indexer because comma expressions are not allowed - // in computed properties. - if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken) { - return true; - } + // Question mark could be an indexer with an optional property, + // or it could be a conditional expression in a computed property. + if (token !== SyntaxKind.QuestionToken) { + return false; + } - // Question mark could be an indexer with an optional property, - // or it could be a conditional expression in a computed property. - if (token !== SyntaxKind.QuestionToken) { - return false; - } - - // If any of the following tokens are after the question mark, it cannot - // be a conditional expression, so treat it as an indexer. - return nextToken() === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBracketToken; - }); + // If any of the following tokens are after the question mark, it cannot + // be a conditional expression, so treat it as an indexer. + nextToken(); + return token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBracketToken; } function parseIndexSignatureDeclaration(fullStart: number, modifiers: ModifiersArray): IndexSignatureDeclaration { @@ -2069,15 +2089,19 @@ module ts { case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties return true; default: - return isLiteralPropertyName() && lookAhead(() => - nextToken() === SyntaxKind.OpenParenToken || - token === SyntaxKind.LessThanToken || - token === SyntaxKind.QuestionToken || - token === SyntaxKind.ColonToken || - canParseSemicolon()); + return isLiteralPropertyName() && lookAhead(isTypeMemberWithLiteralPropertyName); } } + function isTypeMemberWithLiteralPropertyName() { + nextToken(); + return token === SyntaxKind.OpenParenToken || + token === SyntaxKind.LessThanToken || + token === SyntaxKind.QuestionToken || + token === SyntaxKind.ColonToken || + canParseSemicolon(); + } + function parseTypeMember(): Declaration { switch (token) { case SyntaxKind.OpenParenToken: @@ -2087,19 +2111,25 @@ module ts { // Indexer or computed property return isIndexSignature() ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined) : parsePropertyOrMethod(); case SyntaxKind.NewKeyword: - if (lookAhead(() => nextToken() === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken)) { + if (lookAhead(isStartOfConstructSignature)) { return parseSignatureMember(SyntaxKind.ConstructSignature); } + // fall through. case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: return parsePropertyOrMethod(); default: - if (token >= SyntaxKind.Identifier) { + if (isIdentifierOrKeyword()) { return parsePropertyOrMethod(); } } } + function isStartOfConstructSignature() { + nextToken(); + return token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken; + } + function parseTypeLiteral(): TypeLiteralNode { var node = createNode(SyntaxKind.TypeLiteral); node.members = parseObjectTypeMembers(); @@ -2187,15 +2217,17 @@ module ts { case SyntaxKind.OpenParenToken: // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, // or something that starts a type. We don't want to consider things like '(1)' a type. - return lookAhead(() => { - nextToken(); - return token === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType(); - }); + return lookAhead(isStartOfParenthesizedOrFunctionType); default: return isIdentifier(); } } + function isStartOfParenthesizedOrFunctionType() { + nextToken(); + return token === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType(); + } + function parseArrayTypeOrHigher(): TypeNode { var type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { @@ -2224,35 +2256,41 @@ module ts { } function isStartOfFunctionType(): boolean { - return token === SyntaxKind.LessThanToken || token === SyntaxKind.OpenParenToken && lookAhead(() => { + if (token === SyntaxKind.LessThanToken) { + return true; + } + + return token === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType); + } + + function isUnambiguouslyStartOfFunctionType() { + nextToken(); + if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) { + // ( ) + // ( ... + return true; + } + if (isIdentifier() || isModifier(token)) { nextToken(); - if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) { - // ( ) - // ( ... + if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || + token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken || + isIdentifier() || isModifier(token)) { + // ( id : + // ( id , + // ( id ? + // ( id = + // ( modifier id return true; } - if (isIdentifier() || isModifier(token)) { + if (token === SyntaxKind.CloseParenToken) { nextToken(); - if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || - token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken || - isIdentifier() || isModifier(token)) { - // ( id : - // ( id , - // ( id ? - // ( id = - // ( modifier id + if (token === SyntaxKind.EqualsGreaterThanToken) { + // ( id ) => return true; } - if (token === SyntaxKind.CloseParenToken) { - nextToken(); - if (token === SyntaxKind.EqualsGreaterThanToken) { - // ( id ) => - return true; - } - } } - return false; - }); + } + return false; } function parseType(): TypeNode { @@ -2455,15 +2493,17 @@ module ts { // for now we just check if the next token is an identifier. More heuristics // can be added here later as necessary. We just need to make sure that we // don't accidently consume something legal. - return lookAhead(() => { - nextToken(); - return !scanner.hasPrecedingLineBreak() && isIdentifier(); - }); + return lookAhead(nextTokenIsIdentifierOnSameLine); } return false; } + function nextTokenIsIdentifierOnSameLine() { + nextToken(); + return !scanner.hasPrecedingLineBreak() && isIdentifier() + } + function parseYieldExpression(): YieldExpression { var node = createNode(SyntaxKind.YieldExpression); @@ -2546,66 +2586,9 @@ module ts { // Speculatively look ahead to be sure, and rollback if not. function isParenthesizedArrowFunctionExpression(): Tristate { if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { - return lookAhead(() => { - var first = token; - var second = nextToken(); - - if (first === SyntaxKind.OpenParenToken) { - if (second === SyntaxKind.CloseParenToken) { - // Simple cases: "() =>", "(): ", and "() {". - // This is an arrow function with no parameters. - // The last one is not actually an arrow function, - // but this is probably what the user intended. - var third = nextToken(); - switch (third) { - case SyntaxKind.EqualsGreaterThanToken: - case SyntaxKind.ColonToken: - case SyntaxKind.OpenBraceToken: - return Tristate.True; - default: - return Tristate.False; - } - } - - // Simple case: "(..." - // This is an arrow function with a rest parameter. - if (second === SyntaxKind.DotDotDotToken) { - return Tristate.True; - } - - // If we had "(" followed by something that's not an identifier, - // then this definitely doesn't look like a lambda. - // Note: we could be a little more lenient and allow - // "(public" or "(private". These would not ever actually be allowed, - // but we could provide a good error message instead of bailing out. - if (!isIdentifier()) { - return Tristate.False; - } - - // If we have something like "(a:", then we must have a - // type-annotated parameter in an arrow function expression. - if (nextToken() === SyntaxKind.ColonToken) { - return Tristate.True; - } - - // This *could* be a parenthesized arrow function. - // Return Unknown to let the caller know. - return Tristate.Unknown; - } - else { - Debug.assert(first === SyntaxKind.LessThanToken); - - // If we have "<" not followed by an identifier, - // then this definitely is not an arrow function. - if (!isIdentifier()) { - return Tristate.False; - } - - // This *could* be a parenthesized arrow function. - return Tristate.Unknown; - } - }); + return lookAhead(isParenthesizedArrowFunctionExpressionWorker); } + if (token === SyntaxKind.EqualsGreaterThanToken) { // ERROR RECOVERY TWEAK: // If we see a standalone => try to parse it as an arrow function expression as that's @@ -2616,6 +2599,66 @@ module ts { return Tristate.False; } + function isParenthesizedArrowFunctionExpressionWorker() { + var first = token; + var second = nextToken(); + + if (first === SyntaxKind.OpenParenToken) { + if (second === SyntaxKind.CloseParenToken) { + // Simple cases: "() =>", "(): ", and "() {". + // This is an arrow function with no parameters. + // The last one is not actually an arrow function, + // but this is probably what the user intended. + var third = nextToken(); + switch (third) { + case SyntaxKind.EqualsGreaterThanToken: + case SyntaxKind.ColonToken: + case SyntaxKind.OpenBraceToken: + return Tristate.True; + default: + return Tristate.False; + } + } + + // Simple case: "(..." + // This is an arrow function with a rest parameter. + if (second === SyntaxKind.DotDotDotToken) { + return Tristate.True; + } + + // If we had "(" followed by something that's not an identifier, + // then this definitely doesn't look like a lambda. + // Note: we could be a little more lenient and allow + // "(public" or "(private". These would not ever actually be allowed, + // but we could provide a good error message instead of bailing out. + if (!isIdentifier()) { + return Tristate.False; + } + + // If we have something like "(a:", then we must have a + // type-annotated parameter in an arrow function expression. + if (nextToken() === SyntaxKind.ColonToken) { + return Tristate.True; + } + + // This *could* be a parenthesized arrow function. + // Return Unknown to let the caller know. + return Tristate.Unknown; + } + else { + Debug.assert(first === SyntaxKind.LessThanToken); + + // If we have "<" not followed by an identifier, + // then this definitely is not an arrow function. + if (!isIdentifier()) { + return Tristate.False; + } + + // This *could* be a parenthesized arrow function. + return Tristate.Unknown; + } + } + function tryParseSignatureIfArrowOrBraceFollows(): ParsedSignature { return tryParse(() => { // Arrow functions are never generators. @@ -3479,7 +3522,11 @@ module ts { } function isLabel(): boolean { - return isIdentifier() && lookAhead(() => nextToken() === SyntaxKind.ColonToken); + return isIdentifier() && lookAhead(nextTokenIsColonToken); + } + + function nextTokenIsColonToken() { + return nextToken() === SyntaxKind.ColonToken; } function parseLabeledStatement(): LabeledStatement { @@ -3532,7 +3579,7 @@ module ts { // const keyword can precede enum keyword when defining constant enums // 'const enum' do not start statement. // In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier - var isConstEnum = lookAhead(() => nextToken() === SyntaxKind.EnumKeyword); + var isConstEnum = lookAhead(nextTokenIsEnumKeyword); return !isConstEnum; case SyntaxKind.InterfaceKeyword: case SyntaxKind.ClassKeyword: @@ -3551,7 +3598,7 @@ module ts { case SyntaxKind.StaticKeyword: // When followed by an identifier or keyword, these do not start a statement but // might instead be following type members - if (lookAhead(() => nextToken() >= SyntaxKind.Identifier && !scanner.hasPrecedingLineBreak())) { + if (lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine)) { return false; } default: @@ -3559,6 +3606,16 @@ module ts { } } + function nextTokenIsEnumKeyword() { + nextToken(); + return token === SyntaxKind.EnumKeyword + } + + function nextTokenIsIdentifierOrKeywordOnSameLine() { + nextToken(); + return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak(); + } + function parseStatement(): Statement { switch (token) { case SyntaxKind.OpenBraceToken: @@ -3817,7 +3874,7 @@ module ts { } // It is very important that we check this *after* checking indexers because // the [ token can start an index signature or a computed property name - if (token >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || + if (isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBracketToken) { return parsePropertyMemberDeclaration(fullStart, modifiers); } @@ -3975,14 +4032,12 @@ module ts { } function isExternalModuleReference() { - if (token === SyntaxKind.RequireKeyword) { - return lookAhead(() => { - nextToken(); - return token === SyntaxKind.OpenParenToken; - }); - } + return token === SyntaxKind.RequireKeyword && + lookAhead(nextTokenIsOpenParen); + } - return false; + function nextTokenIsOpenParen() { + return nextToken() === SyntaxKind.OpenParenToken; } function parseImportDeclaration(fullStart: number, modifiers: ModifiersArray): ImportDeclaration { @@ -4039,23 +4094,47 @@ module ts { case SyntaxKind.ImportKeyword: case SyntaxKind.TypeKeyword: // Not true keywords so ensure an identifier follows - return lookAhead(() => nextToken() >= SyntaxKind.Identifier); + return lookAhead(nextTokenIsIdentifierOrKeyword); case SyntaxKind.ModuleKeyword: // Not a true keyword so ensure an identifier or string literal follows - return lookAhead(() => nextToken() >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral); + return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral); case SyntaxKind.ExportKeyword: // Check for export assignment or modifier on source element - return lookAhead(() => nextToken() === SyntaxKind.EqualsToken || isDeclarationStart()); + return lookAhead(nextTokenIsEqualsTokenOrDeclarationStart); case SyntaxKind.DeclareKeyword: case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.StaticKeyword: // Check for modifier on source element - return lookAhead(() => { nextToken(); return isDeclarationStart(); }); + return lookAhead(nextTokenIsDeclarationStart); } } + function isIdentifierOrKeyword() { + return token >= SyntaxKind.Identifier; + } + + function nextTokenIsIdentifierOrKeyword() { + nextToken(); + return isIdentifierOrKeyword(); + } + + function nextTokenIsIdentifierOrKeywordOrStringLiteral() { + nextToken(); + return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral; + } + + function nextTokenIsEqualsTokenOrDeclarationStart() { + nextToken(); + return token === SyntaxKind.EqualsToken || isDeclarationStart(); + } + + function nextTokenIsDeclarationStart() { + nextToken(); + return isDeclarationStart(); + } + function parseDeclaration(): ModuleElement { var fullStart = getNodePos(); var modifiers = parseModifiers(); From 8b078c2734f9ce6b4fa3c5f212f966c5c0a27ba0 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 2 Dec 2014 08:46:33 -0800 Subject: [PATCH 31/41] baseline change conflict not caught during github merge --- .../reference/conditionalOperatorConditionIsObjectType.types | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/baselines/reference/conditionalOperatorConditionIsObjectType.types b/tests/baselines/reference/conditionalOperatorConditionIsObjectType.types index 7887f71c2c2..f99c591b593 100644 --- a/tests/baselines/reference/conditionalOperatorConditionIsObjectType.types +++ b/tests/baselines/reference/conditionalOperatorConditionIsObjectType.types @@ -180,7 +180,7 @@ condObject.valueOf() ? exprIsObject1 : exprIsObject2; new Date() ? exprString1 : exprBoolean1; // union >new Date() ? exprString1 : exprBoolean1 : string | boolean >new Date() : Date ->Date : { (): string; new (): Date; new (value: number): Date; new (value: string): Date; new (year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date; prototype: Date; parse(s: string): number; UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number; now(): number; } +>Date : DateConstructor >exprString1 : string >exprBoolean1 : boolean From a6fe980d19c93b8763b00475a1b3e120cc0f3aca Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Dec 2014 13:54:44 -0800 Subject: [PATCH 32/41] Add explanatory comment. Reduce function allocations in the parser. --- src/compiler/parser.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 9397661839d..de2d75286dc 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1395,10 +1395,12 @@ module ts { } function parseContextualModifier(t: SyntaxKind): boolean { - return token === t && tryParse(() => { - nextToken(); - return canFollowModifier(); - }); + return token === t && tryParse(nextTokenCanFollowModifier); + } + + function nextTokenCanFollowModifier() { + nextToken(); + return canFollowModifier(); } function parseAnyContextualModifier(): boolean { @@ -4066,9 +4068,13 @@ module ts { // literals. We check to ensure that it is only a string literal later in the grammar // walker. node.expression = parseExpression(); + + // Ensure the string being required is in our 'identifier' table. This will ensure + // that features like 'find refs' will look inside this file when search for its name. if (node.expression.kind === SyntaxKind.StringLiteral) { internIdentifier((node.expression).text); } + parseExpected(SyntaxKind.CloseParenToken); return finishNode(node); } From a6a7e81de2d27671229d6ed7ce68842f40f974e3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Dec 2014 14:05:35 -0800 Subject: [PATCH 33/41] Add failing test. --- ...oduleReferenceDoubleUnderscore1.errors.txt | 22 +++++++++++++++++++ ...xternalModuleReferenceDoubleUnderscore1.js | 19 ++++++++++++++++ ...xternalModuleReferenceDoubleUnderscore1.ts | 16 ++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.errors.txt create mode 100644 tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.js create mode 100644 tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts diff --git a/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.errors.txt b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.errors.txt new file mode 100644 index 00000000000..80e2725d694 --- /dev/null +++ b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.errors.txt @@ -0,0 +1,22 @@ +tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts(2,29): error TS2307: Cannot find external module '__timezonecomplete/basics'. + + +==== tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts (1 errors) ==== + declare module 'timezonecomplete' { + import basics = require("__timezonecomplete/basics"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2307: Cannot find external module '__timezonecomplete/basics'. + export import TimeUnit = basics.TimeUnit; + } + + declare module '__timezonecomplete/basics' { + export enum TimeUnit { + Second = 0, + Minute = 1, + Hour = 2, + Day = 3, + Week = 4, + Month = 5, + Year = 6, + } + } \ No newline at end of file diff --git a/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.js b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.js new file mode 100644 index 00000000000..f6f9572ba6b --- /dev/null +++ b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.js @@ -0,0 +1,19 @@ +//// [externalModuleReferenceDoubleUnderscore1.ts] +declare module 'timezonecomplete' { + import basics = require("__timezonecomplete/basics"); + export import TimeUnit = basics.TimeUnit; +} + +declare module '__timezonecomplete/basics' { + export enum TimeUnit { + Second = 0, + Minute = 1, + Hour = 2, + Day = 3, + Week = 4, + Month = 5, + Year = 6, + } +} + +//// [externalModuleReferenceDoubleUnderscore1.js] diff --git a/tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts b/tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts new file mode 100644 index 00000000000..1ff020b4919 --- /dev/null +++ b/tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts @@ -0,0 +1,16 @@ +declare module 'timezonecomplete' { + import basics = require("__timezonecomplete/basics"); + export import TimeUnit = basics.TimeUnit; +} + +declare module '__timezonecomplete/basics' { + export enum TimeUnit { + Second = 0, + Minute = 1, + Hour = 2, + Day = 3, + Week = 4, + Month = 5, + Year = 6, + } +} \ No newline at end of file From ec17f369a2acd19a18bcd6e63327c36634093eac Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Dec 2014 14:14:57 -0800 Subject: [PATCH 34/41] Find imported external modules that start with double underscores. --- src/compiler/checker.ts | 16 +++++--- ...oduleReferenceDoubleUnderscore1.errors.txt | 22 ----------- ...rnalModuleReferenceDoubleUnderscore1.types | 37 +++++++++++++++++++ 3 files changed, 47 insertions(+), 28 deletions(-) delete mode 100644 tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.errors.txt create mode 100644 tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4fdab0a44a6..9b6af72eb52 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -545,14 +545,18 @@ module ts { return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\"; } - function resolveExternalModuleName(location: Node, moduleExpression: Expression): Symbol { - if (moduleExpression.kind !== SyntaxKind.StringLiteral) { + function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol { + if (moduleReferenceExpression.kind !== SyntaxKind.StringLiteral) { return; } - var moduleLiteral = moduleExpression; + var moduleReferenceLiteral = moduleReferenceExpression; var searchPath = getDirectoryPath(getSourceFile(location).filename); - var moduleName = moduleLiteral.text; + + // Module names are escaped in our symbol table. However, string literal values aren't. + // Escape the name in the "require(...)" clause to ensure we find the right symbol. + var moduleName = escapeIdentifier(moduleReferenceLiteral.text); + if (!moduleName) return; var isRelative = isExternalModuleNameRelative(moduleName); if (!isRelative) { @@ -573,10 +577,10 @@ module ts { if (sourceFile.symbol) { return getResolvedExportSymbol(sourceFile.symbol); } - error(moduleLiteral, Diagnostics.File_0_is_not_an_external_module, sourceFile.filename); + error(moduleReferenceLiteral, Diagnostics.File_0_is_not_an_external_module, sourceFile.filename); return; } - error(moduleLiteral, Diagnostics.Cannot_find_external_module_0, moduleName); + error(moduleReferenceLiteral, Diagnostics.Cannot_find_external_module_0, moduleName); } function getResolvedExportSymbol(moduleSymbol: Symbol): Symbol { diff --git a/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.errors.txt b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.errors.txt deleted file mode 100644 index 80e2725d694..00000000000 --- a/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.errors.txt +++ /dev/null @@ -1,22 +0,0 @@ -tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts(2,29): error TS2307: Cannot find external module '__timezonecomplete/basics'. - - -==== tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts (1 errors) ==== - declare module 'timezonecomplete' { - import basics = require("__timezonecomplete/basics"); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2307: Cannot find external module '__timezonecomplete/basics'. - export import TimeUnit = basics.TimeUnit; - } - - declare module '__timezonecomplete/basics' { - export enum TimeUnit { - Second = 0, - Minute = 1, - Hour = 2, - Day = 3, - Week = 4, - Month = 5, - Year = 6, - } - } \ No newline at end of file diff --git a/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.types b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.types new file mode 100644 index 00000000000..e255e64d467 --- /dev/null +++ b/tests/baselines/reference/externalModuleReferenceDoubleUnderscore1.types @@ -0,0 +1,37 @@ +=== tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts === +declare module 'timezonecomplete' { + import basics = require("__timezonecomplete/basics"); +>basics : typeof basics + + export import TimeUnit = basics.TimeUnit; +>TimeUnit : typeof basics.TimeUnit +>basics : typeof basics +>TimeUnit : basics.TimeUnit +} + +declare module '__timezonecomplete/basics' { + export enum TimeUnit { +>TimeUnit : TimeUnit + + Second = 0, +>Second : TimeUnit + + Minute = 1, +>Minute : TimeUnit + + Hour = 2, +>Hour : TimeUnit + + Day = 3, +>Day : TimeUnit + + Week = 4, +>Week : TimeUnit + + Month = 5, +>Month : TimeUnit + + Year = 6, +>Year : TimeUnit + } +} From a38e76b882aaf5ce15eabba2b267723a2471a6b1 Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 2 Dec 2014 13:29:49 -0800 Subject: [PATCH 35/41] Address codereview --- src/compiler/emitter.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 303ca6264cb..e71e7920476 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2202,14 +2202,21 @@ module ts { // Emit identifier as an identifier emit(node.name); write(": "); - // Even though this is stored as identified because it is in short-hand property assignment, - // treated it as expression + // Even though this is stored as identifier treat it as an expression + // Short-hand, { x }, is equivalent of normal form { x: x } emitExpressionIdentifier(node.name); emitTrailingComments(node); } function emitShorthandPropertyAssignment(node: ShorthandPropertyDeclaration) { - // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment + // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment. For example: + // module m { + // export var y; + // } + // module m { + // export var obj = { y }; + // } + // The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version var prefix = resolver.getExpressionNamePrefix(node.name); if (prefix) { emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node); @@ -3408,7 +3415,7 @@ module ts { return emitPinnedOrTripleSlashComments(node); } - // Check if node has SyntaxKind which can be emitted regardless of the ScriptTarget + // Check if the node can be emitted regardless of the ScriptTarget switch (node.kind) { case SyntaxKind.Identifier: return emitIdentifier(node); @@ -3542,8 +3549,9 @@ module ts { return emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node); } } - else if (compilerOptions.target >= ScriptTarget.ES6) { + else { // Emit node natively + Debug.assert(compilerOptions.target >= ScriptTarget.ES6, "Invalid ScriptTarget. We should emit as ES6 or above"); switch (node.kind) { case SyntaxKind.ShorthandPropertyAssignment: return emitShorthandPropertyAssignment(node); From ff3d64f83cf70fac24c90fc3a867330f3bb1e252 Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 2 Dec 2014 13:29:49 -0800 Subject: [PATCH 36/41] Address codereview --- src/compiler/emitter.ts | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 303ca6264cb..0a953877866 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2197,22 +2197,29 @@ module ts { emitTrailingComments(node); } - function emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node: ShorthandPropertyDeclaration) { + function emitDownlevelShorthandPropertyAssignment(node: ShorthandPropertyDeclaration) { emitLeadingComments(node); // Emit identifier as an identifier emit(node.name); write(": "); - // Even though this is stored as identified because it is in short-hand property assignment, - // treated it as expression + // Even though this is stored as identifier treat it as an expression + // Short-hand, { x }, is equivalent of normal form { x: x } emitExpressionIdentifier(node.name); emitTrailingComments(node); } function emitShorthandPropertyAssignment(node: ShorthandPropertyDeclaration) { - // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment + // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment. For example: + // module m { + // export var y; + // } + // module m { + // export var obj = { y }; + // } + // The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version var prefix = resolver.getExpressionNamePrefix(node.name); if (prefix) { - emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node); + emitDownlevelShorthandPropertyAssignment(node); } // If short-hand property has no prefix, emit it as short-hand. else { @@ -3408,7 +3415,7 @@ module ts { return emitPinnedOrTripleSlashComments(node); } - // Check if node has SyntaxKind which can be emitted regardless of the ScriptTarget + // Check if the node can be emitted regardless of the ScriptTarget switch (node.kind) { case SyntaxKind.Identifier: return emitIdentifier(node); @@ -3539,11 +3546,12 @@ module ts { // Emit node down-level switch (node.kind) { case SyntaxKind.ShorthandPropertyAssignment: - return emitShorthandPropertyAssignmentAsNormalPropertyAssignment(node); + return emitDownlevelShorthandPropertyAssignment(node); } } - else if (compilerOptions.target >= ScriptTarget.ES6) { + else { // Emit node natively + Debug.assert(compilerOptions.target >= ScriptTarget.ES6, "Invalid ScriptTarget. We should emit as ES6 or above"); switch (node.kind) { case SyntaxKind.ShorthandPropertyAssignment: return emitShorthandPropertyAssignment(node); From 90bf48f2d4baba138a3bbd6edada95679fdcc59d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Dec 2014 14:49:34 -0800 Subject: [PATCH 37/41] Extract reference comments out into their own diagnostics array. Only actual parse errors are stored in parseDiagnostics. Reference errors are stored in a separate array now. --- src/compiler/parser.ts | 96 +++++++++++++++++++++------------------- src/compiler/types.ts | 17 ++++--- src/services/services.ts | 3 ++ 3 files changed, 65 insertions(+), 51 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index de2d75286dc..5acc393c672 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -943,7 +943,6 @@ module ts { } export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, version: string, isOpen: boolean = false): SourceFile { - var file: SourceFile; var scanner: Scanner; var token: SyntaxKind; var parsingContext: ParsingContext; @@ -1101,22 +1100,22 @@ module ts { return getPositionFromLineAndCharacter(getLineStarts(), line, character); } - function error(message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void { + function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void { var start = scanner.getTokenPos(); var length = scanner.getTextPos() - start; - errorAtPosition(start, length, message, arg0, arg1, arg2); + parseErrorAtPosition(start, length, message, arg0, arg1, arg2); } - function errorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void { - var lastErrorPosition = file.parseDiagnostics.length - ? file.parseDiagnostics[file.parseDiagnostics.length - 1].start + function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void { + var lastErrorPosition = sourceFile.parseDiagnostics.length + ? sourceFile.parseDiagnostics[sourceFile.parseDiagnostics.length - 1].start : -1; // Don't report another error if it would just be at the same position as the last error. if (start !== lastErrorPosition) { - var diagnostic = createFileDiagnostic(file, start, length, message, arg0, arg1, arg2); - file.parseDiagnostics.push(diagnostic); + var diagnostic = createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2); + sourceFile.parseDiagnostics.push(diagnostic); } if (lookAheadMode === LookAheadMode.NoErrorYet) { @@ -1126,7 +1125,7 @@ module ts { function scanError(message: DiagnosticMessage) { var pos = scanner.getTextPos(); - errorAtPosition(pos, 0, message); + parseErrorAtPosition(pos, 0, message); } function onComment(pos: number, end: number) { @@ -1165,7 +1164,7 @@ module ts { // Keep track of the state we'll need to rollback to if lookahead fails (or if the // caller asked us to always reset our state). var saveToken = token; - var saveSyntacticErrorsLength = file.parseDiagnostics.length; + var saveSyntacticErrorsLength = sourceFile.parseDiagnostics.length; // Keep track of the current look ahead mode (this matters if we have nested // speculative parsing). @@ -1187,7 +1186,7 @@ module ts { lookAheadMode = saveLookAheadMode; if (!result || alwaysResetState) { token = saveToken; - file.parseDiagnostics.length = saveSyntacticErrorsLength; + sourceFile.parseDiagnostics.length = saveSyntacticErrorsLength; } return result; @@ -1236,10 +1235,10 @@ module ts { // Report specific message if provided with one. Otherwise, report generic fallback message. if (diagnosticMessage) { - error(diagnosticMessage, arg0); + parseErrorAtCurrentToken(diagnosticMessage, arg0); } else { - error(Diagnostics._0_expected, tokenToString(kind)); + parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind)); } return false; } @@ -1307,10 +1306,10 @@ module ts { function createMissingNode(kind: SyntaxKind, reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): Node { if (reportAtCurrentPosition) { - errorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0); + parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0); } else { - error(diagnosticMessage, arg0); + parseErrorAtCurrentToken(diagnosticMessage, arg0); } return createMissingNodeWithoutError(kind); @@ -1601,7 +1600,7 @@ module ts { // Returns true if we should abort parsing. function abortParsingListOrMoveToNextToken(kind: ParsingContext) { - error(parsingContextErrors(kind)); + parseErrorAtCurrentToken(parsingContextErrors(kind)); if (isInSomeParsingContext()) { return true; } @@ -4206,13 +4205,13 @@ module ts { var referencePathMatchResult = getFileReferenceFromReferencePath(comment, range); if (referencePathMatchResult) { var fileReference = referencePathMatchResult.fileReference; - file.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib; + sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib; var diagnosticMessage = referencePathMatchResult.diagnosticMessage; if (fileReference) { referencedFiles.push(fileReference); } if (diagnosticMessage) { - file.parseDiagnostics.push(createFileDiagnostic(file, range.pos, range.end - range.pos, diagnosticMessage)); + sourceFile.referenceDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage)); } } else { @@ -4220,7 +4219,7 @@ module ts { var amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment); if(amdModuleNameMatchResult) { if(amdModuleName) { - file.parseDiagnostics.push(createFileDiagnostic(file, range.pos, range.end - range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments)); + sourceFile.referenceDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments)); } amdModuleName = amdModuleNameMatchResult[2]; } @@ -4241,7 +4240,7 @@ module ts { } function getExternalModuleIndicator() { - return forEach(file.statements, node => + return forEach(sourceFile.statements, node => node.flags & NodeFlags.Export || node.kind === SyntaxKind.ImportDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference || node.kind === SyntaxKind.ExportAssignment @@ -4252,15 +4251,15 @@ module ts { var syntacticDiagnostics: Diagnostic[]; function getSyntacticDiagnostics() { if (syntacticDiagnostics === undefined) { - if (file.parseDiagnostics.length > 0) { + if (sourceFile.parseDiagnostics.length > 0) { // Don't bother doing any grammar checks if there are already parser errors. // Otherwise we may end up with too many cascading errors. - syntacticDiagnostics = file.parseDiagnostics; + syntacticDiagnostics = sourceFile.referenceDiagnostics.concat(sourceFile.parseDiagnostics); } else { // No parser errors were reported. Perform our stricter grammar checks. - syntacticDiagnostics = file.grammarDiagnostics; - checkGrammar(sourceText, languageVersion, file); + checkGrammar(sourceText, languageVersion, sourceFile); + syntacticDiagnostics = sourceFile.referenceDiagnostics.concat(sourceFile.grammarDiagnostics); } } @@ -4273,32 +4272,37 @@ module ts { if (fileExtensionIs(filename, ".d.ts")) { rootNodeFlags = NodeFlags.DeclarationFile; } - file = createRootNode(SyntaxKind.SourceFile, 0, sourceText.length, rootNodeFlags); - file.filename = normalizePath(filename); - file.text = sourceText; - file.getLineAndCharacterFromPosition = getLineAndCharacterFromSourcePosition; - file.getPositionFromLineAndCharacter = getPositionFromSourceLineAndCharacter; - file.getLineStarts = getLineStarts; - file.getSyntacticDiagnostics = getSyntacticDiagnostics; - file.parseDiagnostics = []; - file.grammarDiagnostics = []; - file.semanticDiagnostics = []; + + var sourceFile = createRootNode(SyntaxKind.SourceFile, 0, sourceText.length, rootNodeFlags); + + sourceFile.getLineAndCharacterFromPosition = getLineAndCharacterFromSourcePosition; + sourceFile.getPositionFromLineAndCharacter = getPositionFromSourceLineAndCharacter; + sourceFile.getLineStarts = getLineStarts; + sourceFile.getSyntacticDiagnostics = getSyntacticDiagnostics; + + sourceFile.filename = normalizePath(filename); + sourceFile.text = sourceText; + + sourceFile.referenceDiagnostics = []; + sourceFile.parseDiagnostics = []; + sourceFile.grammarDiagnostics = []; + sourceFile.semanticDiagnostics = []; var referenceComments = processReferenceComments(); - file.referencedFiles = referenceComments.referencedFiles; - file.amdDependencies = referenceComments.amdDependencies; - file.amdModuleName = referenceComments.amdModuleName; + sourceFile.referencedFiles = referenceComments.referencedFiles; + sourceFile.amdDependencies = referenceComments.amdDependencies; + sourceFile.amdModuleName = referenceComments.amdModuleName; - file.statements = parseList(ParsingContext.SourceElements, /*checkForStrictMode*/ true, parseSourceElement); - file.externalModuleIndicator = getExternalModuleIndicator(); + sourceFile.statements = parseList(ParsingContext.SourceElements, /*checkForStrictMode*/ true, parseSourceElement); + sourceFile.externalModuleIndicator = getExternalModuleIndicator(); - file.nodeCount = nodeCount; - file.identifierCount = identifierCount; - file.version = version; - file.isOpen = isOpen; - file.languageVersion = languageVersion; - file.identifiers = identifiers; - return file; + sourceFile.nodeCount = nodeCount; + sourceFile.identifierCount = identifierCount; + sourceFile.version = version; + sourceFile.isOpen = isOpen; + sourceFile.languageVersion = languageVersion; + sourceFile.identifiers = identifiers; + return sourceFile; } function isLeftHandSideExpression(expr: Expression): boolean { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ac94bfae517..e22ae6d8c32 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -795,17 +795,24 @@ module ts { amdDependencies: string[]; amdModuleName: string; referencedFiles: FileReference[]; - semanticDiagnostics: Diagnostic[]; + + // Diagnostics reported about the "/// Date: Tue, 2 Dec 2014 15:04:44 -0800 Subject: [PATCH 38/41] fix crash in signature help --- src/compiler/types.ts | 2 +- src/services/utilities.ts | 4 ---- tests/cases/fourslash/signatureHelpWithUnknown.ts | 6 ++++++ 3 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 tests/cases/fourslash/signatureHelpWithUnknown.ts diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ac94bfae517..db691b09455 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -257,7 +257,7 @@ module ts { LastTypeNode = ParenthesizedType, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, - FirstToken = EndOfFileToken, + FirstToken = Unknown, LastToken = TypeKeyword, FirstTriviaToken = SingleLineCommentTrivia, LastTriviaToken = WhitespaceTrivia, diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 4a3301312fb..9df0476c105 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -280,10 +280,6 @@ module ts { } function nodeHasTokens(n: Node): boolean { - if (n.kind === SyntaxKind.Unknown) { - return false; - } - // If we have a token or node that has a non-zero width, it must have tokens. // Note, that getWidth() does not take trivia into account. return n.getWidth() !== 0; diff --git a/tests/cases/fourslash/signatureHelpWithUnknown.ts b/tests/cases/fourslash/signatureHelpWithUnknown.ts new file mode 100644 index 00000000000..00a031b2673 --- /dev/null +++ b/tests/cases/fourslash/signatureHelpWithUnknown.ts @@ -0,0 +1,6 @@ +/// + +////eval(\/*1*/ + +goTo.marker("1"); +verify.signatureHelpCountIs(1); From 636a466552d6018bb113858ae9ac65e33ed999b7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 2 Dec 2014 15:16:09 -0800 Subject: [PATCH 39/41] Added comment. --- src/services/shims.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/services/shims.ts b/src/services/shims.ts index 64759fffc9f..86671009be2 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -913,6 +913,8 @@ module ts { } } + // Here we expose the TypeScript services as an external module + // so that it may be consumed easily like a node module. declare var module: any; if (typeof module !== "undefined" && module.exports) { module.exports = ts; From 5a7500ca5e62d7e6c7863cf42d156e8bcdc3017c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Dec 2014 16:09:41 -0800 Subject: [PATCH 40/41] Add a dedicated 'EndOfFile' token to a SourceFile. This is important for incremental parsing, as it is where we can attach parse errors at the end of the file to. Also, it helps with things like emitting comments at the end of the file. --- src/compiler/emitter.ts | 3 + src/compiler/parser.ts | 7 +- src/compiler/types.ts | 1 + src/services/services.ts | 4 +- .../reference/anyAssignableToEveryType.js | 5 + .../reference/augmentedTypesClass3.js | 1 + .../baselines/reference/augmentedTypesEnum.js | 3 + .../reference/augmentedTypesEnum2.js | 2 + .../reference/augmentedTypesFunction.js | 3 + .../reference/augmentedTypesInterface.js | 1 + .../reference/augmentedTypesModules.js | 1 + .../baselines/reference/augmentedTypesVar.js | 3 + .../reference/baseIndexSignatureResolution.js | 34 +++ .../reference/commentEmitAtEndOfFile1.js | 22 ++ .../reference/commentEmitAtEndOfFile1.types | 17 ++ .../reference/commentsAtEndOfFile1.js | 1 + ...peratorWithSubtypeObjectOnCallSignature.js | 1 + ...WithSubtypeObjectOnConstructorSignature.js | 1 + ...ubtypeObjectOnInstantiatedCallSignature.js | 1 + ...bjectOnInstantiatedConstructorSignature.js | 1 + tests/baselines/reference/concatError.js | 45 ++++ .../reference/conformanceFunctionOverloads.js | 10 + .../reference/emitCommentsOnlyFile.js | 26 +++ tests/baselines/reference/emitPostComments.js | 26 +++ tests/baselines/reference/emitPreComments.js | 26 +++ tests/baselines/reference/errorSupression1.js | 1 + .../reference/everyTypeAssignableToAny.js | 5 + .../functionConstraintSatisfaction.js | 4 + ...CallWithObjectTypeArgsAndNumericIndexer.js | 7 + ...cCallWithObjectTypeArgsAndStringIndexer.js | 7 + .../reference/heterogeneousArrayLiterals.js | 25 ++ .../innerTypeParameterShadowingOuterOne.js | 8 + .../innerTypeParameterShadowingOuterOne2.js | 10 + .../baselines/reference/moduleIdentifiers.js | 2 + .../reference/nullAssignableToEveryType.js | 5 + .../reference/parserS7.6.1.1_A1.10.js | 8 + .../reference/parserSyntaxWalker.generated.js | 217 ++++++++++++++++++ ...sivelySpecializedConstructorDeclaration.js | 41 ++++ .../baselines/reference/sourceMap-Comment1.js | 1 + .../reference/sourceMap-Comment1.js.map | 2 +- .../sourceMap-Comment1.sourcemap.txt | 13 ++ .../reference/typeParameterAsTypeArgument.js | 10 + ...ParameterUsedAsTypeParameterConstraint3.js | 12 + .../undefinedAssignableToEveryType.js | 5 + tests/baselines/reference/witness.js | 1 + .../cases/compiler/commentEmitAtEndOfFile1.ts | 10 + 46 files changed, 636 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/commentEmitAtEndOfFile1.js create mode 100644 tests/baselines/reference/commentEmitAtEndOfFile1.types create mode 100644 tests/cases/compiler/commentEmitAtEndOfFile1.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b39f58dde0e..7193523bf96 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3443,6 +3443,7 @@ module ts { // Start new file on new line writeLine(); emitDetachedComments(node); + // emit prologue directives prior to __extends var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false); if (!extendsEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitExtends) { @@ -3474,6 +3475,8 @@ module ts { emitCaptureThisForNodeIfNecessary(node); emitLinesStartingAt(node.statements, startIndex); } + + emitLeadingComments(node.endOfFileToken); } function emitNode(node: Node): void { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index aa2a8d5ec4c..06980e19187 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -313,8 +313,10 @@ module ts { case SyntaxKind.FinallyBlock: case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: - case SyntaxKind.SourceFile: return children((node).statements); + case SyntaxKind.SourceFile: + return children((node).statements) || + child((node).endOfFileToken); case SyntaxKind.VariableStatement: return children(node.modifiers) || children((node).declarations); @@ -4294,6 +4296,9 @@ module ts { sourceFile.amdModuleName = referenceComments.amdModuleName; sourceFile.statements = parseList(ParsingContext.SourceElements, /*checkForStrictMode*/ true, parseSourceElement); + Debug.assert(token === SyntaxKind.EndOfFileToken); + sourceFile.endOfFileToken = parseTokenNode(); + sourceFile.externalModuleIndicator = getExternalModuleIndicator(); sourceFile.nodeCount = nodeCount; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 81df5c9c42c..edf052a8876 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -786,6 +786,7 @@ module ts { // Source files are declarations when they are external modules. export interface SourceFile extends Declaration { statements: NodeArray; + endOfFileToken: Node; filename: string; text: string; diff --git a/src/services/services.ts b/src/services/services.ts index 29b7431bb23..44c587974df 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -722,6 +722,9 @@ module ts { public filename: string; public text: string; + public statements: NodeArray; + public endOfFileToken: Node; + // These methods will have their implementation provided by the implementation the // compiler actually exports off of SourceFile. public getLineAndCharacterFromPosition: (position: number) => LineAndCharacter; @@ -743,7 +746,6 @@ module ts { public nodeCount: number; public identifierCount: number; public symbolCount: number; - public statements: NodeArray; public version: string; public isOpen: boolean; public languageVersion: ScriptTarget; diff --git a/tests/baselines/reference/anyAssignableToEveryType.js b/tests/baselines/reference/anyAssignableToEveryType.js index 6c117a5054d..75d847709a5 100644 --- a/tests/baselines/reference/anyAssignableToEveryType.js +++ b/tests/baselines/reference/anyAssignableToEveryType.js @@ -83,3 +83,8 @@ function foo(x, y, z) { y = a; z = a; } +//function foo(x: T, y: U, z: V) { +// x = a; +// y = a; +// z = a; +//} diff --git a/tests/baselines/reference/augmentedTypesClass3.js b/tests/baselines/reference/augmentedTypesClass3.js index dd0da2a1646..b42d9dda356 100644 --- a/tests/baselines/reference/augmentedTypesClass3.js +++ b/tests/baselines/reference/augmentedTypesClass3.js @@ -52,3 +52,4 @@ var c5c = (function () { }; return c5c; })(); +//import c5c = require(''); diff --git a/tests/baselines/reference/augmentedTypesEnum.js b/tests/baselines/reference/augmentedTypesEnum.js index f7a83018cfd..484b0addd58 100644 --- a/tests/baselines/reference/augmentedTypesEnum.js +++ b/tests/baselines/reference/augmentedTypesEnum.js @@ -105,3 +105,6 @@ var e6b; (function (e6b) { e6b.y = 2; })(e6b || (e6b = {})); // should be error +// enum then import, messes with error reporting +//enum e7 { One } +//import e7 = require(''); // should be error diff --git a/tests/baselines/reference/augmentedTypesEnum2.js b/tests/baselines/reference/augmentedTypesEnum2.js index 8ab98a7cb7b..434e508f14c 100644 --- a/tests/baselines/reference/augmentedTypesEnum2.js +++ b/tests/baselines/reference/augmentedTypesEnum2.js @@ -40,3 +40,5 @@ var e2 = (function () { }; return e2; })(); +//enum then enum - covered +//enum then import - covered diff --git a/tests/baselines/reference/augmentedTypesFunction.js b/tests/baselines/reference/augmentedTypesFunction.js index 078854e227c..34567c77e8c 100644 --- a/tests/baselines/reference/augmentedTypesFunction.js +++ b/tests/baselines/reference/augmentedTypesFunction.js @@ -93,3 +93,6 @@ var y5b; })(y5b || (y5b = {})); // should be an error function y5c() { } +// function then import, messes with other errors +//function y6() { } +//import y6 = require(''); diff --git a/tests/baselines/reference/augmentedTypesInterface.js b/tests/baselines/reference/augmentedTypesInterface.js index 709b16d615c..a5039f8b1d0 100644 --- a/tests/baselines/reference/augmentedTypesInterface.js +++ b/tests/baselines/reference/augmentedTypesInterface.js @@ -48,3 +48,4 @@ var i3; i3[i3["One"] = 0] = "One"; })(i3 || (i3 = {})); ; +//import i4 = require(''); // error diff --git a/tests/baselines/reference/augmentedTypesModules.js b/tests/baselines/reference/augmentedTypesModules.js index 0c7967b2227..a9bff3fa74b 100644 --- a/tests/baselines/reference/augmentedTypesModules.js +++ b/tests/baselines/reference/augmentedTypesModules.js @@ -268,3 +268,4 @@ var m6; (function (m6) { m6.y = 2; })(m6 || (m6 = {})); +//import m6 = require(''); diff --git a/tests/baselines/reference/augmentedTypesVar.js b/tests/baselines/reference/augmentedTypesVar.js index 4735d647056..f4404cecb3d 100644 --- a/tests/baselines/reference/augmentedTypesVar.js +++ b/tests/baselines/reference/augmentedTypesVar.js @@ -80,3 +80,6 @@ var x6b; (function (x6b) { x6b.y = 2; })(x6b || (x6b = {})); // error +// var then import, messes with other error reporting +//var x7 = 1; +//import x7 = require(''); diff --git a/tests/baselines/reference/baseIndexSignatureResolution.js b/tests/baselines/reference/baseIndexSignatureResolution.js index 0c1e6c610f3..4c2d63bf2c9 100644 --- a/tests/baselines/reference/baseIndexSignatureResolution.js +++ b/tests/baselines/reference/baseIndexSignatureResolution.js @@ -45,3 +45,37 @@ var Derived = (function (_super) { })(Base); var x = null; var y = x[0]; +/* +// Note - the equivalent for normal interface methods works fine: +interface A { + foo(): Base; +} +interface B extends A { + foo(): TBase; +} +var b: B = null; +var z: Derived = b.foo(); +class Base { private a: string; } +class Derived extends Base { private b: string; } + +// Note - commmenting "extends Foo" prevents the error +interface Foo { + [i: number]: Base; +} +interface FooOf extends Foo { + [i: number]: TBase; +} +var x: FooOf = null; +var y: Derived = x[0]; + +/* +// Note - the equivalent for normal interface methods works fine: +interface A { + foo(): Base; +} +interface B extends A { + foo(): TBase; +} +var b: B = null; +var z: Derived = b.foo(); + diff --git a/tests/baselines/reference/commentEmitAtEndOfFile1.js b/tests/baselines/reference/commentEmitAtEndOfFile1.js new file mode 100644 index 00000000000..1a1f7cb8900 --- /dev/null +++ b/tests/baselines/reference/commentEmitAtEndOfFile1.js @@ -0,0 +1,22 @@ +//// [commentEmitAtEndOfFile1.ts] +// test +var f = '' +// test #2 +module foo { + function bar() { } +} +// test #3 +module empty { +} +// test #4 + +//// [commentEmitAtEndOfFile1.js] +// test +var f = ''; +// test #2 +var foo; +(function (foo) { + function bar() { + } +})(foo || (foo = {})); +// test #4 diff --git a/tests/baselines/reference/commentEmitAtEndOfFile1.types b/tests/baselines/reference/commentEmitAtEndOfFile1.types new file mode 100644 index 00000000000..76b5c868cb6 --- /dev/null +++ b/tests/baselines/reference/commentEmitAtEndOfFile1.types @@ -0,0 +1,17 @@ +=== tests/cases/compiler/commentEmitAtEndOfFile1.ts === +// test +var f = '' +>f : string + +// test #2 +module foo { +>foo : typeof foo + + function bar() { } +>bar : () => void +} +// test #3 +module empty { +>empty : unknown +} +// test #4 diff --git a/tests/baselines/reference/commentsAtEndOfFile1.js b/tests/baselines/reference/commentsAtEndOfFile1.js index a0b0fe3731e..2d4dae39e6b 100644 --- a/tests/baselines/reference/commentsAtEndOfFile1.js +++ b/tests/baselines/reference/commentsAtEndOfFile1.js @@ -6,3 +6,4 @@ Input: //// [commentsAtEndOfFile1.js] Input: ; +//Testing two diff --git a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnCallSignature.js b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnCallSignature.js index 890add6bc8a..5a00fd85f3c 100644 --- a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnCallSignature.js +++ b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnCallSignature.js @@ -501,3 +501,4 @@ var r8b8 = b8 !== a8; var r8b9 = b9 !== a9; var r8b10 = b10 !== a10; var r8b11 = b11 !== a11; +//var r8b12 = b12 !== a12; diff --git a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnConstructorSignature.js b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnConstructorSignature.js index aefeb6d87ff..cba4f67933b 100644 --- a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnConstructorSignature.js +++ b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnConstructorSignature.js @@ -427,3 +427,4 @@ var r8b6 = b6 !== a6; var r8b7 = b7 !== a7; var r8b8 = b8 !== a8; var r8b9 = b9 !== a9; +//var r8b10 = b10 !== a10; diff --git a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedCallSignature.js b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedCallSignature.js index 1a83da3e663..1f2400f9bea 100644 --- a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedCallSignature.js +++ b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedCallSignature.js @@ -316,3 +316,4 @@ var r8b3 = b3 !== a3; var r8b4 = b4 !== a4; var r8b5 = b5 !== a5; var r8b6 = b6 !== a6; +//var r8b7 = b7 !== a7; diff --git a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedConstructorSignature.js b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedConstructorSignature.js index 393a2485c47..e80480e1a4e 100644 --- a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedConstructorSignature.js +++ b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedConstructorSignature.js @@ -316,3 +316,4 @@ var r8b3 = b3 !== a3; var r8b4 = b4 !== a4; var r8b5 = b5 !== a5; var r8b6 = b6 !== a6; +//var r8b7 = b7 !== a7; diff --git a/tests/baselines/reference/concatError.js b/tests/baselines/reference/concatError.js index e4ae4afdb65..04c0a16b836 100644 --- a/tests/baselines/reference/concatError.js +++ b/tests/baselines/reference/concatError.js @@ -43,3 +43,48 @@ interface Array { var fa; fa = fa.concat([0]); fa = fa.concat(0); +/* + + + + +declare class C { + public m(p1: C>): C; + //public p: T; +} + +var c: C; +var cc: C>; + +c = c.m(cc); +var n1: number[]; +/* +interface Array { + concat(...items: T[][]): T[]; // Note: This overload needs to be picked for arrays of arrays, even though both are applicable + concat(...items: T[]): T[]; +} +*/ +var fa: number[]; + +fa = fa.concat([0]); +fa = fa.concat(0); + + + + + +/* + + + + +declare class C { + public m(p1: C>): C; + //public p: T; +} + +var c: C; +var cc: C>; + +c = c.m(cc); + diff --git a/tests/baselines/reference/conformanceFunctionOverloads.js b/tests/baselines/reference/conformanceFunctionOverloads.js index 15dec719e40..b245f6a2c91 100644 --- a/tests/baselines/reference/conformanceFunctionOverloads.js +++ b/tests/baselines/reference/conformanceFunctionOverloads.js @@ -25,3 +25,13 @@ //// [conformanceFunctionOverloads.js] // Function overloads do not emit code +// Function overload signature with optional parameter +// Function overload signature with optional parameter +// Function overloads with generic and non-generic overloads +// Function overloads whose only difference is returning different unconstrained generic parameters +// Function overloads whose only difference is returning different constrained generic parameters +// Function overloads that differ only by type parameter constraints +// Function overloads with matching accessibility +// Function overloads with matching export +// Function overloads with more params than implementation signature +// Function overloads where return types are same infinitely recursive type reference diff --git a/tests/baselines/reference/emitCommentsOnlyFile.js b/tests/baselines/reference/emitCommentsOnlyFile.js index 263e9dd2588..d720dc3c191 100644 --- a/tests/baselines/reference/emitCommentsOnlyFile.js +++ b/tests/baselines/reference/emitCommentsOnlyFile.js @@ -29,3 +29,29 @@ //// [emitCommentsOnlyFile.js] +/** +* @name Foo +* @class +*/ +/**#@+ +* @memberOf Foo# +* @field +*/ +/** +* @name bar +* @type Object[] +*/ +/**#@-*/ +/** +* @name Foo2 +* @class +*/ +/**#@+ +* @memberOf Foo2# +* @field +*/ +/** +* @name bar +* @type Object[] +*/ +/**#@-*/ diff --git a/tests/baselines/reference/emitPostComments.js b/tests/baselines/reference/emitPostComments.js index 98d1d59457b..8a5736af00d 100644 --- a/tests/baselines/reference/emitPostComments.js +++ b/tests/baselines/reference/emitPostComments.js @@ -31,3 +31,29 @@ var y = 10; //// [emitPostComments.js] var y = 10; +/** +* @name Foo +* @class +*/ +/**#@+ +* @memberOf Foo# +* @field +*/ +/** +* @name bar +* @type Object[] +*/ +/**#@-*/ +/** +* @name Foo2 +* @class +*/ +/**#@+ +* @memberOf Foo2# +* @field +*/ +/** +* @name bar +* @type Object[] +*/ +/**#@-*/ diff --git a/tests/baselines/reference/emitPreComments.js b/tests/baselines/reference/emitPreComments.js index 5a79a430175..4ca3297fce7 100644 --- a/tests/baselines/reference/emitPreComments.js +++ b/tests/baselines/reference/emitPreComments.js @@ -33,3 +33,29 @@ var y = 10; //// [emitPreComments.js] // This is pre comment var y = 10; +/** +* @name Foo +* @class +*/ +/**#@+ +* @memberOf Foo# +* @field +*/ +/** +* @name bar +* @type Object[] +*/ +/**#@-*/ +/** +* @name Foo2 +* @class +*/ +/**#@+ +* @memberOf Foo2# +* @field +*/ +/** +* @name bar +* @type Object[] +*/ +/**#@-*/ diff --git a/tests/baselines/reference/errorSupression1.js b/tests/baselines/reference/errorSupression1.js index 92330a6c074..059530be452 100644 --- a/tests/baselines/reference/errorSupression1.js +++ b/tests/baselines/reference/errorSupression1.js @@ -20,3 +20,4 @@ var Foo = (function () { var baz = Foo.b; // Foo.b won't bind. baz.concat("y"); +// So we don't want an error on 'concat'. diff --git a/tests/baselines/reference/everyTypeAssignableToAny.js b/tests/baselines/reference/everyTypeAssignableToAny.js index 5ff22ce1962..8730167c3ff 100644 --- a/tests/baselines/reference/everyTypeAssignableToAny.js +++ b/tests/baselines/reference/everyTypeAssignableToAny.js @@ -113,3 +113,8 @@ function foo(x, y, z) { a = y; a = z; } +//function foo(x: T, y: U, z: V) { +// a = x; +// a = y; +// a = z; +//} diff --git a/tests/baselines/reference/functionConstraintSatisfaction.js b/tests/baselines/reference/functionConstraintSatisfaction.js index 452080917db..a16f4d1ed36 100644 --- a/tests/baselines/reference/functionConstraintSatisfaction.js +++ b/tests/baselines/reference/functionConstraintSatisfaction.js @@ -113,3 +113,7 @@ function foo2(x, y) { foo(x); foo(y); } +//function foo2(x: T, y: U) { +// foo(x); +// foo(y); +//} diff --git a/tests/baselines/reference/genericCallWithObjectTypeArgsAndNumericIndexer.js b/tests/baselines/reference/genericCallWithObjectTypeArgsAndNumericIndexer.js index aa2da602e25..f300e3a8093 100644 --- a/tests/baselines/reference/genericCallWithObjectTypeArgsAndNumericIndexer.js +++ b/tests/baselines/reference/genericCallWithObjectTypeArgsAndNumericIndexer.js @@ -57,3 +57,10 @@ function other3(arg) { // BUG 821629 //var u: U = r2[1]; // ok } +//function other3(arg: T) { +// var b: { [x: number]: T }; +// var r2 = foo(b); +// var d = r2[1]; +// // BUG 821629 +// //var u: U = r2[1]; // ok +//} diff --git a/tests/baselines/reference/genericCallWithObjectTypeArgsAndStringIndexer.js b/tests/baselines/reference/genericCallWithObjectTypeArgsAndStringIndexer.js index c810ce01fd4..eee87caf3de 100644 --- a/tests/baselines/reference/genericCallWithObjectTypeArgsAndStringIndexer.js +++ b/tests/baselines/reference/genericCallWithObjectTypeArgsAndStringIndexer.js @@ -58,3 +58,10 @@ function other3(arg) { // BUG 821629 //var u: U = r2['hm']; // ok } +//function other3(arg: T) { +// var b: { [x: string]: T }; +// var r2 = foo(b); +// var d: Date = r2['hm']; // ok +// // BUG 821629 +// //var u: U = r2['hm']; // ok +//} diff --git a/tests/baselines/reference/heterogeneousArrayLiterals.js b/tests/baselines/reference/heterogeneousArrayLiterals.js index 8deb3b4b068..4ac929305c0 100644 --- a/tests/baselines/reference/heterogeneousArrayLiterals.js +++ b/tests/baselines/reference/heterogeneousArrayLiterals.js @@ -241,3 +241,28 @@ function foo4(t, u) { var j = [u, derived]; // Derived[] var k = [t, u]; } +//function foo3(t: T, u: U) { +// var a = [t, t]; // T[] +// var b = [t, null]; // T[] +// var c = [t, u]; // {}[] +// var d = [t, 1]; // {}[] +// var e = [() => t, () => u]; // {}[] +// var f = [() => t, () => u, () => null]; // { (): any }[] +// var g = [t, base]; // Base[] +// var h = [t, derived]; // Derived[] +// var i = [u, base]; // Base[] +// var j = [u, derived]; // Derived[] +//} +//function foo4(t: T, u: U) { +// var a = [t, t]; // T[] +// var b = [t, null]; // T[] +// var c = [t, u]; // BUG 821629 +// var d = [t, 1]; // {}[] +// var e = [() => t, () => u]; // {}[] +// var f = [() => t, () => u, () => null]; // { (): any }[] +// var g = [t, base]; // Base[] +// var h = [t, derived]; // Derived[] +// var i = [u, base]; // Base[] +// var j = [u, derived]; // Derived[] +// var k: Base[] = [t, u]; +//} diff --git a/tests/baselines/reference/innerTypeParameterShadowingOuterOne.js b/tests/baselines/reference/innerTypeParameterShadowingOuterOne.js index 81ed990532c..74354468e32 100644 --- a/tests/baselines/reference/innerTypeParameterShadowingOuterOne.js +++ b/tests/baselines/reference/innerTypeParameterShadowingOuterOne.js @@ -47,3 +47,11 @@ function f2() { var x; x.getDate(); } +//function f2() { +// function g() { +// var x: U; +// x.toFixed(); +// } +// var x: U; +// x.getDate(); +//} diff --git a/tests/baselines/reference/innerTypeParameterShadowingOuterOne2.js b/tests/baselines/reference/innerTypeParameterShadowingOuterOne2.js index 8a5a9448f18..36a250d365d 100644 --- a/tests/baselines/reference/innerTypeParameterShadowingOuterOne2.js +++ b/tests/baselines/reference/innerTypeParameterShadowingOuterOne2.js @@ -66,3 +66,13 @@ var C2 = (function () { }; return C2; })(); +//class C2 { +// g() { +// var x: U; +// x.toFixed(); +// } +// h() { +// var x: U; +// x.getDate(); +// } +//} diff --git a/tests/baselines/reference/moduleIdentifiers.js b/tests/baselines/reference/moduleIdentifiers.js index e2050d98f5d..04d39019482 100644 --- a/tests/baselines/reference/moduleIdentifiers.js +++ b/tests/baselines/reference/moduleIdentifiers.js @@ -18,3 +18,5 @@ var M; //var p: M.P; //var m: M = M; var x1 = M.a; +//var x2 = m.a; +//var q: m.P; diff --git a/tests/baselines/reference/nullAssignableToEveryType.js b/tests/baselines/reference/nullAssignableToEveryType.js index 4901f4837bb..9917ebeac9e 100644 --- a/tests/baselines/reference/nullAssignableToEveryType.js +++ b/tests/baselines/reference/nullAssignableToEveryType.js @@ -80,3 +80,8 @@ function foo(x, y, z) { y = null; z = null; } +//function foo(x: T, y: U, z: V) { +// x = null; +// y = null; +// z = null; +//} diff --git a/tests/baselines/reference/parserS7.6.1.1_A1.10.js b/tests/baselines/reference/parserS7.6.1.1_A1.10.js index 04e0076b16a..6465281d88d 100644 --- a/tests/baselines/reference/parserS7.6.1.1_A1.10.js +++ b/tests/baselines/reference/parserS7.6.1.1_A1.10.js @@ -17,3 +17,11 @@ //// [parserS7.6.1.1_A1.10.js] // Copyright 2009 the Sputnik authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. +/** + * The "for" token can not be used as identifier + * + * @path ch07/7.6/7.6.1/7.6.1.1/S7.6.1.1_A1.10.js + * @description Checking if execution of "for=1" fails + * @negative + */ +//for = 1; diff --git a/tests/baselines/reference/parserSyntaxWalker.generated.js b/tests/baselines/reference/parserSyntaxWalker.generated.js index 3b78baa0f74..392b5545830 100644 --- a/tests/baselines/reference/parserSyntaxWalker.generated.js +++ b/tests/baselines/reference/parserSyntaxWalker.generated.js @@ -289,3 +289,220 @@ // [index: number]: string; // } //} +//import fs = module("fs"); +//module TypeScriptAllInOne { +// export class Program { +// static Main(...args: string[]) { +// try { +// var bfs = new BasicFeatures(); +// var retValue: number = 0; +// retValue = bfs.VARIABLES(); +// if (retValue != 0) { +// return 1; +// } +// retValue = bfs.STATEMENTS(4); +// if (retValue != 0) { +// return 1; +// } +// retValue = bfs.TYPES(); +// if (retValue != 0) { +// return 1; +// } +// retValue = bfs.OPERATOR(); +// if (retValue != 0) { +// return 1; +// } +// } +// catch (e) { +// console.log(e); +// } +// finally { +// } +// console.log('Done'); +// return 0; +// } +// } +// class BasicFeatures { +// /// +// /// Test various of variables. Including nullable,key world as variable,special format +// /// +// /// +// public VARIABLES(): number { +// var local = Number.MAX_VALUE; +// var min = Number.MIN_VALUE; +// var inf = Number.NEGATIVE_INFINITY; +// var nan = Number.NaN; +// var undef = undefined; +// var п = local; +// var м = local; +// var local5 = null; +// var local6 = local5 instanceof fs.File; +// var hex = 0xBADC0DE, Hex = 0XDEADBEEF; +// var float = 6.02e23, float2 = 6.02E-23 +// var char = 'c', \u0066 = '\u0066', hexchar = '\x42'; +// var quoted = '"', quoted2 = "'"; +// var reg = /\w*/; +// var objLit = { "var": number = 42, equals: function (x) { return x["var"] === 42; }, toString: () => 'objLit{42}' }; +// var weekday = Weekdays.Monday; +// var con = char + f + hexchar + float.toString() + float2.toString() + reg.toString() + objLit + weekday; +// // +// var any = 0; +// var boolean = 0; +// var declare = 0; +// var constructor = 0; +// var get = 0; +// var implements = 0; +// var interface = 0; +// var let = 0; +// var module = 0; +// var number = 0; +// var package = 0; +// var private = 0; +// var protected = 0; +// var public = 0; +// var set = 0; +// var static = 0; +// var string = 0; +// var yield = 0; +// var sum3 = any + boolean + declare + constructor + get + implements + interface + let + module + number + package + private + protected + public + set + static + string + yield; +// return 0; +// } +// /// +// /// Test different statements. Including if-else,swith,foreach,(un)checked,lock,using,try-catch-finally +// /// +// /// +// /// +// STATEMENTS(i: number): number { +// var retVal = 0; +// if (i == 1) +// retVal = 1; +// else +// retVal = 0; +// switch (i) { +// case 2: +// retVal = 1; +// break; +// case 3: +// retVal = 1; +// break; +// default: +// break; +// } +// for (var x in { x: 0, y: 1 }) { +// } +// try { +// throw null; +// } +// catch (Exception) { +// } +// finally { +// try { } +// catch (Exception) { } +// } +// return retVal; +// } +// /// +// /// Test types in ts language. Including class,struct,interface,delegate,anonymous type +// /// +// /// +// public TYPES(): number { +// var retVal = 0; +// var c = new CLASS(); +// var xx: IF = c; +// retVal += c.Property; +// retVal += c.Member(); +// retVal += xx ^= Foo() ? 0 : 1; +// //anonymous type +// var anony = { a: new CLASS() }; +// retVal += anony.a.d(); +// return retVal; +// } +// ///// +// ///// Test different operators +// ///// +// ///// +// public OPERATOR(): number { +// var a: number[] = [1, 2, 3, 4, implements , ];/*[] bug*/ // YES [] +// var i = a[1];/*[]*/ +// i = i + i - i * i / i % i & i | i ^ i;/*+ - * / % & | ^*/ +// var b = true && false || true ^ false;/*& | ^*/ +// b = !b;/*!*/ +// i = ~i;/*~i*/ +// b = i < (i - continue ) && (i + 1) > i;/*< && >*/ +// var f = true ? 1 : 0;/*? :*/ // YES : +// i++;/*++*/ +// i--;/*--*/ +// b = true && false || true;/*&& ||*/ +// i = i << 5;/*<<*/ +// i = i >> 5;/*>>*/ +// var j = i; +// b = i == j && i != j && i <= j && i >= j;/*= == && != <= >=*/ +// i += 5.0;/*+=*/ +// i -= i;/*-=*/ +// i *= i;/**=*/ +// if (i == 0) +// i++; +// i /= i;/*/=*/ +// i %= i;/*%=*/ +// i &= i;/*&=*/ +// i |= i;/*|=*/ +// i ^= i;/*^=*/ +// i <<= i;/*<<=*/ +// i >>= i;/*>>=*/ +// if (i == 0 && !b && f == 1) +// return 0; +// else return 1; +// } +// } +// interface IF { +// Foo