From 2cc6c4cc289c1e6f8d622a8c5da616357d1230f0 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 14:28:35 -0800 Subject: [PATCH 01/24] Fixed test to explicitly have return type annotation. --- .../types/stringLiteral/stringLiteralTypesOverloads01.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts index d88167eaeff..00441134405 100644 --- a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts @@ -9,7 +9,7 @@ function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; function getFalsyPrimitive(x: "number" | "string"): number | string; function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; -function getFalsyPrimitive(x: PrimitiveName) { +function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { if (x === "string") { return ""; } From 5ef8a306422abded21cb09e87f6b4cada7d4fb2d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 14:34:20 -0800 Subject: [PATCH 02/24] Accepted baselines. --- .../reference/stringLiteralTypesOverloads01.errors.txt | 8 ++++---- .../baselines/reference/stringLiteralTypesOverloads01.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt b/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt index 1592427208b..0a3fdb91929 100644 --- a/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt +++ b/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts(11,10): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts(7,10): error TS2394: Overload signature is not compatible with function implementation. ==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts (1 errors) ==== @@ -9,12 +9,12 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts(11, function getFalsyPrimitive(x: "number"): number; function getFalsyPrimitive(x: "boolean"): boolean; function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; + ~~~~~~~~~~~~~~~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; function getFalsyPrimitive(x: "number" | "string"): number | string; function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; - function getFalsyPrimitive(x: PrimitiveName) { - ~~~~~~~~~~~~~~~~~ -!!! error TS2354: No best common type exists among return expressions. + function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { if (x === "string") { return ""; } diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.js b/tests/baselines/reference/stringLiteralTypesOverloads01.js index 73dabd26fab..f3331c9f717 100644 --- a/tests/baselines/reference/stringLiteralTypesOverloads01.js +++ b/tests/baselines/reference/stringLiteralTypesOverloads01.js @@ -9,7 +9,7 @@ function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; function getFalsyPrimitive(x: "number" | "string"): number | string; function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; -function getFalsyPrimitive(x: PrimitiveName) { +function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { if (x === "string") { return ""; } From 2c2b8be2386f5a29b085ecb489b22786b8acba03 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 14:53:05 -0800 Subject: [PATCH 03/24] Remove empty test. --- .../functions/conformanceFunctionOverloads.ts | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 tests/cases/conformance/functions/conformanceFunctionOverloads.ts diff --git a/tests/cases/conformance/functions/conformanceFunctionOverloads.ts b/tests/cases/conformance/functions/conformanceFunctionOverloads.ts deleted file mode 100644 index f1e08782a51..00000000000 --- a/tests/cases/conformance/functions/conformanceFunctionOverloads.ts +++ /dev/null @@ -1,22 +0,0 @@ -// 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 - From 820a2cb257ae3926b7752c69f0bf31959e4114bb Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 15:03:58 -0800 Subject: [PATCH 04/24] Added some tests for overload compatibility. --- tests/cases/compiler/functionOverloads43.ts | 12 +++++++++++ tests/cases/compiler/functionOverloads44.ts | 22 +++++++++++++++++++++ tests/cases/compiler/functionOverloads45.ts | 22 +++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/cases/compiler/functionOverloads43.ts create mode 100644 tests/cases/compiler/functionOverloads44.ts create mode 100644 tests/cases/compiler/functionOverloads45.ts diff --git a/tests/cases/compiler/functionOverloads43.ts b/tests/cases/compiler/functionOverloads43.ts new file mode 100644 index 00000000000..8822fd86c1b --- /dev/null +++ b/tests/cases/compiler/functionOverloads43.ts @@ -0,0 +1,12 @@ +function foo(bar: { a:number }[]): number; +function foo(bar: { a:string }[]): string; +function foo([x]: { a:number | string }[]): string | number { + if (x) { + return x.a; + } + + return undefined; +} + +var x = foo([{a: "str"}]); +var y = foo([{a: 100}]); \ No newline at end of file diff --git a/tests/cases/compiler/functionOverloads44.ts b/tests/cases/compiler/functionOverloads44.ts new file mode 100644 index 00000000000..20a7ed540f0 --- /dev/null +++ b/tests/cases/compiler/functionOverloads44.ts @@ -0,0 +1,22 @@ +interface Animal { animal } +interface Dog extends Animal { dog } +interface Cat extends Animal { cat } + +function foo1(bar: { a:number }[]): Dog; +function foo1(bar: { a:string }[]): Animal; +function foo1([x]: { a:number | string }[]): Dog { + return undefined; +} + +function foo2(bar: { a:number }[]): Cat; +function foo2(bar: { a:string }[]): Cat | Dog; +function foo2([x]: { a:number | string }[]): Cat { + return undefined; +} + + +var x1 = foo1([{a: "str"}]); +var y1 = foo1([{a: 100}]); + +var x2 = foo2([{a: "str"}]); +var y2 = foo2([{a: 100}]); \ No newline at end of file diff --git a/tests/cases/compiler/functionOverloads45.ts b/tests/cases/compiler/functionOverloads45.ts new file mode 100644 index 00000000000..6210bd13427 --- /dev/null +++ b/tests/cases/compiler/functionOverloads45.ts @@ -0,0 +1,22 @@ +interface Animal { animal } +interface Dog extends Animal { dog } +interface Cat extends Animal { cat } + +function foo1(bar: { a:number }[]): Cat; +function foo1(bar: { a:string }[]): Dog; +function foo1([x]: { a:number | string }[]): Animal { + return undefined; +} + +function foo2(bar: { a:number }[]): Cat; +function foo2(bar: { a:string }[]): Dog; +function foo2([x]: { a:number | string }[]): Cat | Dog { + return undefined; +} + + +var x1 = foo1([{a: "str"}]); +var y1 = foo1([{a: 100}]); + +var x2 = foo2([{a: "str"}]); +var y2 = foo2([{a: 100}]); \ No newline at end of file From 5d94e48e42a680eabb5969bb62047c6f9277a788 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 15:12:52 -0800 Subject: [PATCH 05/24] Accepted baselines. --- .../reference/conformanceFunctionOverloads.js | 37 ------- .../conformanceFunctionOverloads.symbols | 25 ----- .../conformanceFunctionOverloads.types | 25 ----- .../reference/functionOverloads43.errors.txt | 18 ++++ .../reference/functionOverloads43.js | 24 +++++ .../reference/functionOverloads44.js | 37 +++++++ .../reference/functionOverloads44.symbols | 81 ++++++++++++++++ .../reference/functionOverloads44.types | 97 +++++++++++++++++++ .../reference/functionOverloads45.errors.txt | 31 ++++++ .../reference/functionOverloads45.js | 37 +++++++ 10 files changed, 325 insertions(+), 87 deletions(-) delete mode 100644 tests/baselines/reference/conformanceFunctionOverloads.js delete mode 100644 tests/baselines/reference/conformanceFunctionOverloads.symbols delete mode 100644 tests/baselines/reference/conformanceFunctionOverloads.types create mode 100644 tests/baselines/reference/functionOverloads43.errors.txt create mode 100644 tests/baselines/reference/functionOverloads43.js create mode 100644 tests/baselines/reference/functionOverloads44.js create mode 100644 tests/baselines/reference/functionOverloads44.symbols create mode 100644 tests/baselines/reference/functionOverloads44.types create mode 100644 tests/baselines/reference/functionOverloads45.errors.txt create mode 100644 tests/baselines/reference/functionOverloads45.js diff --git a/tests/baselines/reference/conformanceFunctionOverloads.js b/tests/baselines/reference/conformanceFunctionOverloads.js deleted file mode 100644 index b245f6a2c91..00000000000 --- a/tests/baselines/reference/conformanceFunctionOverloads.js +++ /dev/null @@ -1,37 +0,0 @@ -//// [conformanceFunctionOverloads.ts] -// 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 - - - -//// [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/conformanceFunctionOverloads.symbols b/tests/baselines/reference/conformanceFunctionOverloads.symbols deleted file mode 100644 index a80814ea93e..00000000000 --- a/tests/baselines/reference/conformanceFunctionOverloads.symbols +++ /dev/null @@ -1,25 +0,0 @@ -=== tests/cases/conformance/functions/conformanceFunctionOverloads.ts === -// Function overloads do not emit code -No type information for this code. -No type information for this code.// Function overload signature with optional parameter -No type information for this code. -No type information for this code.// Function overload signature with optional parameter -No type information for this code. -No type information for this code.// Function overloads with generic and non-generic overloads -No type information for this code. -No type information for this code.// Function overloads whose only difference is returning different unconstrained generic parameters -No type information for this code. -No type information for this code.// Function overloads whose only difference is returning different constrained generic parameters -No type information for this code. -No type information for this code.// Function overloads that differ only by type parameter constraints -No type information for this code. -No type information for this code.// Function overloads with matching accessibility -No type information for this code. -No type information for this code.// Function overloads with matching export -No type information for this code. -No type information for this code.// Function overloads with more params than implementation signature -No type information for this code. -No type information for this code.// Function overloads where return types are same infinitely recursive type reference -No type information for this code. -No type information for this code. -No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/conformanceFunctionOverloads.types b/tests/baselines/reference/conformanceFunctionOverloads.types deleted file mode 100644 index a80814ea93e..00000000000 --- a/tests/baselines/reference/conformanceFunctionOverloads.types +++ /dev/null @@ -1,25 +0,0 @@ -=== tests/cases/conformance/functions/conformanceFunctionOverloads.ts === -// Function overloads do not emit code -No type information for this code. -No type information for this code.// Function overload signature with optional parameter -No type information for this code. -No type information for this code.// Function overload signature with optional parameter -No type information for this code. -No type information for this code.// Function overloads with generic and non-generic overloads -No type information for this code. -No type information for this code.// Function overloads whose only difference is returning different unconstrained generic parameters -No type information for this code. -No type information for this code.// Function overloads whose only difference is returning different constrained generic parameters -No type information for this code. -No type information for this code.// Function overloads that differ only by type parameter constraints -No type information for this code. -No type information for this code.// Function overloads with matching accessibility -No type information for this code. -No type information for this code.// Function overloads with matching export -No type information for this code. -No type information for this code.// Function overloads with more params than implementation signature -No type information for this code. -No type information for this code.// Function overloads where return types are same infinitely recursive type reference -No type information for this code. -No type information for this code. -No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads43.errors.txt b/tests/baselines/reference/functionOverloads43.errors.txt new file mode 100644 index 00000000000..769bb467186 --- /dev/null +++ b/tests/baselines/reference/functionOverloads43.errors.txt @@ -0,0 +1,18 @@ +tests/cases/compiler/functionOverloads43.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. + + +==== tests/cases/compiler/functionOverloads43.ts (1 errors) ==== + function foo(bar: { a:number }[]): number; + ~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function foo(bar: { a:string }[]): string; + function foo([x]: { a:number | string }[]): string | number { + if (x) { + return x.a; + } + + return undefined; + } + + var x = foo([{a: "str"}]); + var y = foo([{a: 100}]); \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads43.js b/tests/baselines/reference/functionOverloads43.js new file mode 100644 index 00000000000..2bb4b61af14 --- /dev/null +++ b/tests/baselines/reference/functionOverloads43.js @@ -0,0 +1,24 @@ +//// [functionOverloads43.ts] +function foo(bar: { a:number }[]): number; +function foo(bar: { a:string }[]): string; +function foo([x]: { a:number | string }[]): string | number { + if (x) { + return x.a; + } + + return undefined; +} + +var x = foo([{a: "str"}]); +var y = foo([{a: 100}]); + +//// [functionOverloads43.js] +function foo(_a) { + var x = _a[0]; + if (x) { + return x.a; + } + return undefined; +} +var x = foo([{ a: "str" }]); +var y = foo([{ a: 100 }]); diff --git a/tests/baselines/reference/functionOverloads44.js b/tests/baselines/reference/functionOverloads44.js new file mode 100644 index 00000000000..916204d123c --- /dev/null +++ b/tests/baselines/reference/functionOverloads44.js @@ -0,0 +1,37 @@ +//// [functionOverloads44.ts] +interface Animal { animal } +interface Dog extends Animal { dog } +interface Cat extends Animal { cat } + +function foo1(bar: { a:number }[]): Dog; +function foo1(bar: { a:string }[]): Animal; +function foo1([x]: { a:number | string }[]): Dog { + return undefined; +} + +function foo2(bar: { a:number }[]): Cat; +function foo2(bar: { a:string }[]): Cat | Dog; +function foo2([x]: { a:number | string }[]): Cat { + return undefined; +} + + +var x1 = foo1([{a: "str"}]); +var y1 = foo1([{a: 100}]); + +var x2 = foo2([{a: "str"}]); +var y2 = foo2([{a: 100}]); + +//// [functionOverloads44.js] +function foo1(_a) { + var x = _a[0]; + return undefined; +} +function foo2(_a) { + var x = _a[0]; + return undefined; +} +var x1 = foo1([{ a: "str" }]); +var y1 = foo1([{ a: 100 }]); +var x2 = foo2([{ a: "str" }]); +var y2 = foo2([{ a: 100 }]); diff --git a/tests/baselines/reference/functionOverloads44.symbols b/tests/baselines/reference/functionOverloads44.symbols new file mode 100644 index 00000000000..3520777a835 --- /dev/null +++ b/tests/baselines/reference/functionOverloads44.symbols @@ -0,0 +1,81 @@ +=== tests/cases/compiler/functionOverloads44.ts === +interface Animal { animal } +>Animal : Symbol(Animal, Decl(functionOverloads44.ts, 0, 0)) +>animal : Symbol(animal, Decl(functionOverloads44.ts, 0, 18)) + +interface Dog extends Animal { dog } +>Dog : Symbol(Dog, Decl(functionOverloads44.ts, 0, 27)) +>Animal : Symbol(Animal, Decl(functionOverloads44.ts, 0, 0)) +>dog : Symbol(dog, Decl(functionOverloads44.ts, 1, 30)) + +interface Cat extends Animal { cat } +>Cat : Symbol(Cat, Decl(functionOverloads44.ts, 1, 36)) +>Animal : Symbol(Animal, Decl(functionOverloads44.ts, 0, 0)) +>cat : Symbol(cat, Decl(functionOverloads44.ts, 2, 30)) + +function foo1(bar: { a:number }[]): Dog; +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>bar : Symbol(bar, Decl(functionOverloads44.ts, 4, 14)) +>a : Symbol(a, Decl(functionOverloads44.ts, 4, 20)) +>Dog : Symbol(Dog, Decl(functionOverloads44.ts, 0, 27)) + +function foo1(bar: { a:string }[]): Animal; +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>bar : Symbol(bar, Decl(functionOverloads44.ts, 5, 14)) +>a : Symbol(a, Decl(functionOverloads44.ts, 5, 20)) +>Animal : Symbol(Animal, Decl(functionOverloads44.ts, 0, 0)) + +function foo1([x]: { a:number | string }[]): Dog { +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>x : Symbol(x, Decl(functionOverloads44.ts, 6, 15)) +>a : Symbol(a, Decl(functionOverloads44.ts, 6, 20)) +>Dog : Symbol(Dog, Decl(functionOverloads44.ts, 0, 27)) + + return undefined; +>undefined : Symbol(undefined) +} + +function foo2(bar: { a:number }[]): Cat; +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>bar : Symbol(bar, Decl(functionOverloads44.ts, 10, 14)) +>a : Symbol(a, Decl(functionOverloads44.ts, 10, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads44.ts, 1, 36)) + +function foo2(bar: { a:string }[]): Cat | Dog; +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>bar : Symbol(bar, Decl(functionOverloads44.ts, 11, 14)) +>a : Symbol(a, Decl(functionOverloads44.ts, 11, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads44.ts, 1, 36)) +>Dog : Symbol(Dog, Decl(functionOverloads44.ts, 0, 27)) + +function foo2([x]: { a:number | string }[]): Cat { +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>x : Symbol(x, Decl(functionOverloads44.ts, 12, 15)) +>a : Symbol(a, Decl(functionOverloads44.ts, 12, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads44.ts, 1, 36)) + + return undefined; +>undefined : Symbol(undefined) +} + + +var x1 = foo1([{a: "str"}]); +>x1 : Symbol(x1, Decl(functionOverloads44.ts, 17, 3)) +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>a : Symbol(a, Decl(functionOverloads44.ts, 17, 16)) + +var y1 = foo1([{a: 100}]); +>y1 : Symbol(y1, Decl(functionOverloads44.ts, 18, 3)) +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>a : Symbol(a, Decl(functionOverloads44.ts, 18, 16)) + +var x2 = foo2([{a: "str"}]); +>x2 : Symbol(x2, Decl(functionOverloads44.ts, 20, 3)) +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>a : Symbol(a, Decl(functionOverloads44.ts, 20, 16)) + +var y2 = foo2([{a: 100}]); +>y2 : Symbol(y2, Decl(functionOverloads44.ts, 21, 3)) +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>a : Symbol(a, Decl(functionOverloads44.ts, 21, 16)) + diff --git a/tests/baselines/reference/functionOverloads44.types b/tests/baselines/reference/functionOverloads44.types new file mode 100644 index 00000000000..56cad09b472 --- /dev/null +++ b/tests/baselines/reference/functionOverloads44.types @@ -0,0 +1,97 @@ +=== tests/cases/compiler/functionOverloads44.ts === +interface Animal { animal } +>Animal : Animal +>animal : any + +interface Dog extends Animal { dog } +>Dog : Dog +>Animal : Animal +>dog : any + +interface Cat extends Animal { cat } +>Cat : Cat +>Animal : Animal +>cat : any + +function foo1(bar: { a:number }[]): Dog; +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>bar : { a: number; }[] +>a : number +>Dog : Dog + +function foo1(bar: { a:string }[]): Animal; +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>bar : { a: string; }[] +>a : string +>Animal : Animal + +function foo1([x]: { a:number | string }[]): Dog { +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>x : { a: number | string; } +>a : number | string +>Dog : Dog + + return undefined; +>undefined : undefined +} + +function foo2(bar: { a:number }[]): Cat; +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>bar : { a: number; }[] +>a : number +>Cat : Cat + +function foo2(bar: { a:string }[]): Cat | Dog; +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>bar : { a: string; }[] +>a : string +>Cat : Cat +>Dog : Dog + +function foo2([x]: { a:number | string }[]): Cat { +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>x : { a: number | string; } +>a : number | string +>Cat : Cat + + return undefined; +>undefined : undefined +} + + +var x1 = foo1([{a: "str"}]); +>x1 : Animal +>foo1([{a: "str"}]) : Animal +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y1 = foo1([{a: 100}]); +>y1 : Dog +>foo1([{a: 100}]) : Dog +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + +var x2 = foo2([{a: "str"}]); +>x2 : Cat | Dog +>foo2([{a: "str"}]) : Cat | Dog +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y2 = foo2([{a: 100}]); +>y2 : Cat +>foo2([{a: 100}]) : Cat +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + diff --git a/tests/baselines/reference/functionOverloads45.errors.txt b/tests/baselines/reference/functionOverloads45.errors.txt new file mode 100644 index 00000000000..38ed387d9a1 --- /dev/null +++ b/tests/baselines/reference/functionOverloads45.errors.txt @@ -0,0 +1,31 @@ +tests/cases/compiler/functionOverloads45.ts(5,10): error TS2394: Overload signature is not compatible with function implementation. +tests/cases/compiler/functionOverloads45.ts(11,10): error TS2394: Overload signature is not compatible with function implementation. + + +==== tests/cases/compiler/functionOverloads45.ts (2 errors) ==== + interface Animal { animal } + interface Dog extends Animal { dog } + interface Cat extends Animal { cat } + + function foo1(bar: { a:number }[]): Cat; + ~~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function foo1(bar: { a:string }[]): Dog; + function foo1([x]: { a:number | string }[]): Animal { + return undefined; + } + + function foo2(bar: { a:number }[]): Cat; + ~~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function foo2(bar: { a:string }[]): Dog; + function foo2([x]: { a:number | string }[]): Cat | Dog { + return undefined; + } + + + var x1 = foo1([{a: "str"}]); + var y1 = foo1([{a: 100}]); + + var x2 = foo2([{a: "str"}]); + var y2 = foo2([{a: 100}]); \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads45.js b/tests/baselines/reference/functionOverloads45.js new file mode 100644 index 00000000000..89bf41893c9 --- /dev/null +++ b/tests/baselines/reference/functionOverloads45.js @@ -0,0 +1,37 @@ +//// [functionOverloads45.ts] +interface Animal { animal } +interface Dog extends Animal { dog } +interface Cat extends Animal { cat } + +function foo1(bar: { a:number }[]): Cat; +function foo1(bar: { a:string }[]): Dog; +function foo1([x]: { a:number | string }[]): Animal { + return undefined; +} + +function foo2(bar: { a:number }[]): Cat; +function foo2(bar: { a:string }[]): Dog; +function foo2([x]: { a:number | string }[]): Cat | Dog { + return undefined; +} + + +var x1 = foo1([{a: "str"}]); +var y1 = foo1([{a: 100}]); + +var x2 = foo2([{a: "str"}]); +var y2 = foo2([{a: 100}]); + +//// [functionOverloads45.js] +function foo1(_a) { + var x = _a[0]; + return undefined; +} +function foo2(_a) { + var x = _a[0]; + return undefined; +} +var x1 = foo1([{ a: "str" }]); +var y1 = foo1([{ a: 100 }]); +var x2 = foo2([{ a: "str" }]); +var y2 = foo2([{ a: 100 }]); From dc2af2fb7fd1ca54e05c8cc211d05041b23dc708 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 17:08:23 -0800 Subject: [PATCH 06/24] Use different relation for overload compatibility. --- src/compiler/checker.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 30d4818592b..212d863e575 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4959,6 +4959,25 @@ namespace ts { return checkTypeRelatedTo(sourceType, targetType, assignableRelation, /*errorNode*/ undefined); } + function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean { + const erasedSource = getErasedSignature(implementation); + const erasedTarget = getErasedSignature(overload); + + const sourceReturnType = getReturnTypeOfSignature(erasedSource); + const targetReturnType = getReturnTypeOfSignature(erasedTarget); + if (checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined) + || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined)) { + const anyReturningSource = cloneSignature(erasedSource); + const anyReturningTarget = cloneSignature(erasedTarget); + anyReturningSource.resolvedReturnType = anyType; + anyReturningTarget.resolvedReturnType = anyType; + + const anyReturningSourceType = getOrCreateTypeFromSignature(anyReturningSource); + const anyReturningTargetType = getOrCreateTypeFromSignature(anyReturningTarget); + return checkTypeRelatedTo(anyReturningSourceType, anyReturningTargetType, assignableRelation, /*errorNode*/ undefined); + } + } + /** * Checks if 'source' is related to 'target' (e.g.: is a assignable to). * @param source The left-hand-side of the relation. @@ -11683,7 +11702,7 @@ namespace ts { // // The implementation is completely unrelated to the specialized signature, yet we do not check this. for (const signature of signatures) { - if (!signature.hasStringLiterals && !isSignatureAssignableTo(bodySignature, signature)) { + if (!signature.hasStringLiterals && !isImplementationCompatibleWithOverload(bodySignature, signature)) { error(signature.declaration, Diagnostics.Overload_signature_is_not_compatible_with_function_implementation); break; } From e1004fac60608142dff3941ef0ac586c71942fc8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 17:13:16 -0800 Subject: [PATCH 07/24] Removed misleading comment from test. --- tests/cases/compiler/overloadOnConstConstraintChecks4.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/compiler/overloadOnConstConstraintChecks4.ts b/tests/cases/compiler/overloadOnConstConstraintChecks4.ts index f63c5b46349..55425f63393 100644 --- a/tests/cases/compiler/overloadOnConstConstraintChecks4.ts +++ b/tests/cases/compiler/overloadOnConstConstraintChecks4.ts @@ -6,7 +6,7 @@ class C extends A { } function foo(name: 'hi'): B; function foo(name: 'bye'): C; -function foo(name: string): A; // error +function foo(name: string): A; function foo(name: any): Z { return null; } From 51d240989aada5f805808c4a1025f13ecbfba68f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 17:13:46 -0800 Subject: [PATCH 08/24] Accepted baselines. --- .../reference/functionOverloads22.errors.txt | 10 - .../reference/functionOverloads22.symbols | 19 ++ .../reference/functionOverloads22.types | 22 +++ .../reference/functionOverloads43.errors.txt | 18 -- .../reference/functionOverloads43.symbols | 39 ++++ .../reference/functionOverloads43.types | 47 +++++ .../reference/functionOverloads45.errors.txt | 31 ---- .../reference/functionOverloads45.symbols | 81 ++++++++ .../reference/functionOverloads45.types | 97 ++++++++++ ...verloadOnConstConstraintChecks4.errors.txt | 19 -- .../overloadOnConstConstraintChecks4.js | 2 +- .../overloadOnConstConstraintChecks4.symbols | 43 +++++ .../overloadOnConstConstraintChecks4.types | 45 +++++ .../stringLiteralTypesOverloads01.errors.txt | 59 ------ .../stringLiteralTypesOverloads01.symbols | 144 +++++++++++++++ .../stringLiteralTypesOverloads01.types | 174 ++++++++++++++++++ 16 files changed, 712 insertions(+), 138 deletions(-) delete mode 100644 tests/baselines/reference/functionOverloads22.errors.txt create mode 100644 tests/baselines/reference/functionOverloads22.symbols create mode 100644 tests/baselines/reference/functionOverloads22.types delete mode 100644 tests/baselines/reference/functionOverloads43.errors.txt create mode 100644 tests/baselines/reference/functionOverloads43.symbols create mode 100644 tests/baselines/reference/functionOverloads43.types delete mode 100644 tests/baselines/reference/functionOverloads45.errors.txt create mode 100644 tests/baselines/reference/functionOverloads45.symbols create mode 100644 tests/baselines/reference/functionOverloads45.types delete mode 100644 tests/baselines/reference/overloadOnConstConstraintChecks4.errors.txt create mode 100644 tests/baselines/reference/overloadOnConstConstraintChecks4.symbols create mode 100644 tests/baselines/reference/overloadOnConstConstraintChecks4.types delete mode 100644 tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads01.types diff --git a/tests/baselines/reference/functionOverloads22.errors.txt b/tests/baselines/reference/functionOverloads22.errors.txt deleted file mode 100644 index c9fc8aa2b2f..00000000000 --- a/tests/baselines/reference/functionOverloads22.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -tests/cases/compiler/functionOverloads22.ts(2,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/compiler/functionOverloads22.ts (1 errors) ==== - function foo(bar:number):{a:number;}[]; - function foo(bar:string):{a:number; b:string;}[]; - ~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo(bar:any):{a:any;b?:any;}[] { return [{a:""}] } - \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads22.symbols b/tests/baselines/reference/functionOverloads22.symbols new file mode 100644 index 00000000000..7924da073b0 --- /dev/null +++ b/tests/baselines/reference/functionOverloads22.symbols @@ -0,0 +1,19 @@ +=== tests/cases/compiler/functionOverloads22.ts === +function foo(bar:number):{a:number;}[]; +>foo : Symbol(foo, Decl(functionOverloads22.ts, 0, 0), Decl(functionOverloads22.ts, 0, 39), Decl(functionOverloads22.ts, 1, 49)) +>bar : Symbol(bar, Decl(functionOverloads22.ts, 0, 13)) +>a : Symbol(a, Decl(functionOverloads22.ts, 0, 26)) + +function foo(bar:string):{a:number; b:string;}[]; +>foo : Symbol(foo, Decl(functionOverloads22.ts, 0, 0), Decl(functionOverloads22.ts, 0, 39), Decl(functionOverloads22.ts, 1, 49)) +>bar : Symbol(bar, Decl(functionOverloads22.ts, 1, 13)) +>a : Symbol(a, Decl(functionOverloads22.ts, 1, 26)) +>b : Symbol(b, Decl(functionOverloads22.ts, 1, 35)) + +function foo(bar:any):{a:any;b?:any;}[] { return [{a:""}] } +>foo : Symbol(foo, Decl(functionOverloads22.ts, 0, 0), Decl(functionOverloads22.ts, 0, 39), Decl(functionOverloads22.ts, 1, 49)) +>bar : Symbol(bar, Decl(functionOverloads22.ts, 2, 13)) +>a : Symbol(a, Decl(functionOverloads22.ts, 2, 23)) +>b : Symbol(b, Decl(functionOverloads22.ts, 2, 29)) +>a : Symbol(a, Decl(functionOverloads22.ts, 2, 51)) + diff --git a/tests/baselines/reference/functionOverloads22.types b/tests/baselines/reference/functionOverloads22.types new file mode 100644 index 00000000000..7557b1c049f --- /dev/null +++ b/tests/baselines/reference/functionOverloads22.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/functionOverloads22.ts === +function foo(bar:number):{a:number;}[]; +>foo : { (bar: number): { a: number; }[]; (bar: string): { a: number; b: string; }[]; } +>bar : number +>a : number + +function foo(bar:string):{a:number; b:string;}[]; +>foo : { (bar: number): { a: number; }[]; (bar: string): { a: number; b: string; }[]; } +>bar : string +>a : number +>b : string + +function foo(bar:any):{a:any;b?:any;}[] { return [{a:""}] } +>foo : { (bar: number): { a: number; }[]; (bar: string): { a: number; b: string; }[]; } +>bar : any +>a : any +>b : any +>[{a:""}] : { a: string; }[] +>{a:""} : { a: string; } +>a : string +>"" : string + diff --git a/tests/baselines/reference/functionOverloads43.errors.txt b/tests/baselines/reference/functionOverloads43.errors.txt deleted file mode 100644 index 769bb467186..00000000000 --- a/tests/baselines/reference/functionOverloads43.errors.txt +++ /dev/null @@ -1,18 +0,0 @@ -tests/cases/compiler/functionOverloads43.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/compiler/functionOverloads43.ts (1 errors) ==== - function foo(bar: { a:number }[]): number; - ~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo(bar: { a:string }[]): string; - function foo([x]: { a:number | string }[]): string | number { - if (x) { - return x.a; - } - - return undefined; - } - - var x = foo([{a: "str"}]); - var y = foo([{a: 100}]); \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads43.symbols b/tests/baselines/reference/functionOverloads43.symbols new file mode 100644 index 00000000000..179ba3e3fed --- /dev/null +++ b/tests/baselines/reference/functionOverloads43.symbols @@ -0,0 +1,39 @@ +=== tests/cases/compiler/functionOverloads43.ts === +function foo(bar: { a:number }[]): number; +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>bar : Symbol(bar, Decl(functionOverloads43.ts, 0, 13)) +>a : Symbol(a, Decl(functionOverloads43.ts, 0, 19)) + +function foo(bar: { a:string }[]): string; +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>bar : Symbol(bar, Decl(functionOverloads43.ts, 1, 13)) +>a : Symbol(a, Decl(functionOverloads43.ts, 1, 19)) + +function foo([x]: { a:number | string }[]): string | number { +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>x : Symbol(x, Decl(functionOverloads43.ts, 2, 14)) +>a : Symbol(a, Decl(functionOverloads43.ts, 2, 19)) + + if (x) { +>x : Symbol(x, Decl(functionOverloads43.ts, 2, 14)) + + return x.a; +>x.a : Symbol(a, Decl(functionOverloads43.ts, 2, 19)) +>x : Symbol(x, Decl(functionOverloads43.ts, 2, 14)) +>a : Symbol(a, Decl(functionOverloads43.ts, 2, 19)) + } + + return undefined; +>undefined : Symbol(undefined) +} + +var x = foo([{a: "str"}]); +>x : Symbol(x, Decl(functionOverloads43.ts, 10, 3)) +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>a : Symbol(a, Decl(functionOverloads43.ts, 10, 14)) + +var y = foo([{a: 100}]); +>y : Symbol(y, Decl(functionOverloads43.ts, 11, 3)) +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>a : Symbol(a, Decl(functionOverloads43.ts, 11, 14)) + diff --git a/tests/baselines/reference/functionOverloads43.types b/tests/baselines/reference/functionOverloads43.types new file mode 100644 index 00000000000..7c0fa8eb818 --- /dev/null +++ b/tests/baselines/reference/functionOverloads43.types @@ -0,0 +1,47 @@ +=== tests/cases/compiler/functionOverloads43.ts === +function foo(bar: { a:number }[]): number; +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>bar : { a: number; }[] +>a : number + +function foo(bar: { a:string }[]): string; +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>bar : { a: string; }[] +>a : string + +function foo([x]: { a:number | string }[]): string | number { +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>x : { a: number | string; } +>a : number | string + + if (x) { +>x : { a: number | string; } + + return x.a; +>x.a : number | string +>x : { a: number | string; } +>a : number | string + } + + return undefined; +>undefined : undefined +} + +var x = foo([{a: "str"}]); +>x : string +>foo([{a: "str"}]) : string +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y = foo([{a: 100}]); +>y : number +>foo([{a: 100}]) : number +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + diff --git a/tests/baselines/reference/functionOverloads45.errors.txt b/tests/baselines/reference/functionOverloads45.errors.txt deleted file mode 100644 index 38ed387d9a1..00000000000 --- a/tests/baselines/reference/functionOverloads45.errors.txt +++ /dev/null @@ -1,31 +0,0 @@ -tests/cases/compiler/functionOverloads45.ts(5,10): error TS2394: Overload signature is not compatible with function implementation. -tests/cases/compiler/functionOverloads45.ts(11,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/compiler/functionOverloads45.ts (2 errors) ==== - interface Animal { animal } - interface Dog extends Animal { dog } - interface Cat extends Animal { cat } - - function foo1(bar: { a:number }[]): Cat; - ~~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo1(bar: { a:string }[]): Dog; - function foo1([x]: { a:number | string }[]): Animal { - return undefined; - } - - function foo2(bar: { a:number }[]): Cat; - ~~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo2(bar: { a:string }[]): Dog; - function foo2([x]: { a:number | string }[]): Cat | Dog { - return undefined; - } - - - var x1 = foo1([{a: "str"}]); - var y1 = foo1([{a: 100}]); - - var x2 = foo2([{a: "str"}]); - var y2 = foo2([{a: 100}]); \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads45.symbols b/tests/baselines/reference/functionOverloads45.symbols new file mode 100644 index 00000000000..28599339099 --- /dev/null +++ b/tests/baselines/reference/functionOverloads45.symbols @@ -0,0 +1,81 @@ +=== tests/cases/compiler/functionOverloads45.ts === +interface Animal { animal } +>Animal : Symbol(Animal, Decl(functionOverloads45.ts, 0, 0)) +>animal : Symbol(animal, Decl(functionOverloads45.ts, 0, 18)) + +interface Dog extends Animal { dog } +>Dog : Symbol(Dog, Decl(functionOverloads45.ts, 0, 27)) +>Animal : Symbol(Animal, Decl(functionOverloads45.ts, 0, 0)) +>dog : Symbol(dog, Decl(functionOverloads45.ts, 1, 30)) + +interface Cat extends Animal { cat } +>Cat : Symbol(Cat, Decl(functionOverloads45.ts, 1, 36)) +>Animal : Symbol(Animal, Decl(functionOverloads45.ts, 0, 0)) +>cat : Symbol(cat, Decl(functionOverloads45.ts, 2, 30)) + +function foo1(bar: { a:number }[]): Cat; +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>bar : Symbol(bar, Decl(functionOverloads45.ts, 4, 14)) +>a : Symbol(a, Decl(functionOverloads45.ts, 4, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads45.ts, 1, 36)) + +function foo1(bar: { a:string }[]): Dog; +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>bar : Symbol(bar, Decl(functionOverloads45.ts, 5, 14)) +>a : Symbol(a, Decl(functionOverloads45.ts, 5, 20)) +>Dog : Symbol(Dog, Decl(functionOverloads45.ts, 0, 27)) + +function foo1([x]: { a:number | string }[]): Animal { +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>x : Symbol(x, Decl(functionOverloads45.ts, 6, 15)) +>a : Symbol(a, Decl(functionOverloads45.ts, 6, 20)) +>Animal : Symbol(Animal, Decl(functionOverloads45.ts, 0, 0)) + + return undefined; +>undefined : Symbol(undefined) +} + +function foo2(bar: { a:number }[]): Cat; +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>bar : Symbol(bar, Decl(functionOverloads45.ts, 10, 14)) +>a : Symbol(a, Decl(functionOverloads45.ts, 10, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads45.ts, 1, 36)) + +function foo2(bar: { a:string }[]): Dog; +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>bar : Symbol(bar, Decl(functionOverloads45.ts, 11, 14)) +>a : Symbol(a, Decl(functionOverloads45.ts, 11, 20)) +>Dog : Symbol(Dog, Decl(functionOverloads45.ts, 0, 27)) + +function foo2([x]: { a:number | string }[]): Cat | Dog { +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>x : Symbol(x, Decl(functionOverloads45.ts, 12, 15)) +>a : Symbol(a, Decl(functionOverloads45.ts, 12, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads45.ts, 1, 36)) +>Dog : Symbol(Dog, Decl(functionOverloads45.ts, 0, 27)) + + return undefined; +>undefined : Symbol(undefined) +} + + +var x1 = foo1([{a: "str"}]); +>x1 : Symbol(x1, Decl(functionOverloads45.ts, 17, 3)) +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>a : Symbol(a, Decl(functionOverloads45.ts, 17, 16)) + +var y1 = foo1([{a: 100}]); +>y1 : Symbol(y1, Decl(functionOverloads45.ts, 18, 3)) +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>a : Symbol(a, Decl(functionOverloads45.ts, 18, 16)) + +var x2 = foo2([{a: "str"}]); +>x2 : Symbol(x2, Decl(functionOverloads45.ts, 20, 3)) +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>a : Symbol(a, Decl(functionOverloads45.ts, 20, 16)) + +var y2 = foo2([{a: 100}]); +>y2 : Symbol(y2, Decl(functionOverloads45.ts, 21, 3)) +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>a : Symbol(a, Decl(functionOverloads45.ts, 21, 16)) + diff --git a/tests/baselines/reference/functionOverloads45.types b/tests/baselines/reference/functionOverloads45.types new file mode 100644 index 00000000000..257a615e334 --- /dev/null +++ b/tests/baselines/reference/functionOverloads45.types @@ -0,0 +1,97 @@ +=== tests/cases/compiler/functionOverloads45.ts === +interface Animal { animal } +>Animal : Animal +>animal : any + +interface Dog extends Animal { dog } +>Dog : Dog +>Animal : Animal +>dog : any + +interface Cat extends Animal { cat } +>Cat : Cat +>Animal : Animal +>cat : any + +function foo1(bar: { a:number }[]): Cat; +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>bar : { a: number; }[] +>a : number +>Cat : Cat + +function foo1(bar: { a:string }[]): Dog; +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>bar : { a: string; }[] +>a : string +>Dog : Dog + +function foo1([x]: { a:number | string }[]): Animal { +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>x : { a: number | string; } +>a : number | string +>Animal : Animal + + return undefined; +>undefined : undefined +} + +function foo2(bar: { a:number }[]): Cat; +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>bar : { a: number; }[] +>a : number +>Cat : Cat + +function foo2(bar: { a:string }[]): Dog; +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>bar : { a: string; }[] +>a : string +>Dog : Dog + +function foo2([x]: { a:number | string }[]): Cat | Dog { +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>x : { a: number | string; } +>a : number | string +>Cat : Cat +>Dog : Dog + + return undefined; +>undefined : undefined +} + + +var x1 = foo1([{a: "str"}]); +>x1 : Dog +>foo1([{a: "str"}]) : Dog +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y1 = foo1([{a: 100}]); +>y1 : Cat +>foo1([{a: 100}]) : Cat +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + +var x2 = foo2([{a: "str"}]); +>x2 : Dog +>foo2([{a: "str"}]) : Dog +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y2 = foo2([{a: 100}]); +>y2 : Cat +>foo2([{a: 100}]) : Cat +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + diff --git a/tests/baselines/reference/overloadOnConstConstraintChecks4.errors.txt b/tests/baselines/reference/overloadOnConstConstraintChecks4.errors.txt deleted file mode 100644 index 7a8037b3dd7..00000000000 --- a/tests/baselines/reference/overloadOnConstConstraintChecks4.errors.txt +++ /dev/null @@ -1,19 +0,0 @@ -tests/cases/compiler/overloadOnConstConstraintChecks4.ts(9,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/compiler/overloadOnConstConstraintChecks4.ts (1 errors) ==== - class Z { } - class A extends Z { private x = 1 } - class B extends A {} - class C extends A { - public foo() { } - } - function foo(name: 'hi'): B; - function foo(name: 'bye'): C; - function foo(name: string): A; // error - ~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo(name: any): Z { - return null; - } - \ No newline at end of file diff --git a/tests/baselines/reference/overloadOnConstConstraintChecks4.js b/tests/baselines/reference/overloadOnConstConstraintChecks4.js index 17ec3779620..c0422e3611e 100644 --- a/tests/baselines/reference/overloadOnConstConstraintChecks4.js +++ b/tests/baselines/reference/overloadOnConstConstraintChecks4.js @@ -7,7 +7,7 @@ class C extends A { } function foo(name: 'hi'): B; function foo(name: 'bye'): C; -function foo(name: string): A; // error +function foo(name: string): A; function foo(name: any): Z { return null; } diff --git a/tests/baselines/reference/overloadOnConstConstraintChecks4.symbols b/tests/baselines/reference/overloadOnConstConstraintChecks4.symbols new file mode 100644 index 00000000000..6e2a34b55e9 --- /dev/null +++ b/tests/baselines/reference/overloadOnConstConstraintChecks4.symbols @@ -0,0 +1,43 @@ +=== tests/cases/compiler/overloadOnConstConstraintChecks4.ts === +class Z { } +>Z : Symbol(Z, Decl(overloadOnConstConstraintChecks4.ts, 0, 0)) + +class A extends Z { private x = 1 } +>A : Symbol(A, Decl(overloadOnConstConstraintChecks4.ts, 0, 11)) +>Z : Symbol(Z, Decl(overloadOnConstConstraintChecks4.ts, 0, 0)) +>x : Symbol(x, Decl(overloadOnConstConstraintChecks4.ts, 1, 19)) + +class B extends A {} +>B : Symbol(B, Decl(overloadOnConstConstraintChecks4.ts, 1, 35)) +>A : Symbol(A, Decl(overloadOnConstConstraintChecks4.ts, 0, 11)) + +class C extends A { +>C : Symbol(C, Decl(overloadOnConstConstraintChecks4.ts, 2, 20)) +>A : Symbol(A, Decl(overloadOnConstConstraintChecks4.ts, 0, 11)) + + public foo() { } +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 3, 19)) +} +function foo(name: 'hi'): B; +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 5, 1), Decl(overloadOnConstConstraintChecks4.ts, 6, 28), Decl(overloadOnConstConstraintChecks4.ts, 7, 29), Decl(overloadOnConstConstraintChecks4.ts, 8, 30)) +>name : Symbol(name, Decl(overloadOnConstConstraintChecks4.ts, 6, 13)) +>B : Symbol(B, Decl(overloadOnConstConstraintChecks4.ts, 1, 35)) + +function foo(name: 'bye'): C; +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 5, 1), Decl(overloadOnConstConstraintChecks4.ts, 6, 28), Decl(overloadOnConstConstraintChecks4.ts, 7, 29), Decl(overloadOnConstConstraintChecks4.ts, 8, 30)) +>name : Symbol(name, Decl(overloadOnConstConstraintChecks4.ts, 7, 13)) +>C : Symbol(C, Decl(overloadOnConstConstraintChecks4.ts, 2, 20)) + +function foo(name: string): A; +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 5, 1), Decl(overloadOnConstConstraintChecks4.ts, 6, 28), Decl(overloadOnConstConstraintChecks4.ts, 7, 29), Decl(overloadOnConstConstraintChecks4.ts, 8, 30)) +>name : Symbol(name, Decl(overloadOnConstConstraintChecks4.ts, 8, 13)) +>A : Symbol(A, Decl(overloadOnConstConstraintChecks4.ts, 0, 11)) + +function foo(name: any): Z { +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 5, 1), Decl(overloadOnConstConstraintChecks4.ts, 6, 28), Decl(overloadOnConstConstraintChecks4.ts, 7, 29), Decl(overloadOnConstConstraintChecks4.ts, 8, 30)) +>name : Symbol(name, Decl(overloadOnConstConstraintChecks4.ts, 9, 13)) +>Z : Symbol(Z, Decl(overloadOnConstConstraintChecks4.ts, 0, 0)) + + return null; +} + diff --git a/tests/baselines/reference/overloadOnConstConstraintChecks4.types b/tests/baselines/reference/overloadOnConstConstraintChecks4.types new file mode 100644 index 00000000000..6ca7288ead9 --- /dev/null +++ b/tests/baselines/reference/overloadOnConstConstraintChecks4.types @@ -0,0 +1,45 @@ +=== tests/cases/compiler/overloadOnConstConstraintChecks4.ts === +class Z { } +>Z : Z + +class A extends Z { private x = 1 } +>A : A +>Z : Z +>x : number +>1 : number + +class B extends A {} +>B : B +>A : A + +class C extends A { +>C : C +>A : A + + public foo() { } +>foo : () => void +} +function foo(name: 'hi'): B; +>foo : { (name: "hi"): B; (name: "bye"): C; (name: string): A; } +>name : "hi" +>B : B + +function foo(name: 'bye'): C; +>foo : { (name: "hi"): B; (name: "bye"): C; (name: string): A; } +>name : "bye" +>C : C + +function foo(name: string): A; +>foo : { (name: "hi"): B; (name: "bye"): C; (name: string): A; } +>name : string +>A : A + +function foo(name: any): Z { +>foo : { (name: "hi"): B; (name: "bye"): C; (name: string): A; } +>name : any +>Z : Z + + return null; +>null : null +} + diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt b/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt deleted file mode 100644 index 0a3fdb91929..00000000000 --- a/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt +++ /dev/null @@ -1,59 +0,0 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts(7,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts (1 errors) ==== - - type PrimitiveName = 'string' | 'number' | 'boolean'; - - function getFalsyPrimitive(x: "string"): string; - function getFalsyPrimitive(x: "number"): number; - function getFalsyPrimitive(x: "boolean"): boolean; - function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; - ~~~~~~~~~~~~~~~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; - function getFalsyPrimitive(x: "number" | "string"): number | string; - function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; - function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { - if (x === "string") { - return ""; - } - if (x === "number") { - return 0; - } - if (x === "boolean") { - return false; - } - - // Should be unreachable. - throw "Invalid value"; - } - - namespace Consts1 { - const EMPTY_STRING = getFalsyPrimitive("string"); - const ZERO = getFalsyPrimitive('number'); - const FALSE = getFalsyPrimitive("boolean"); - } - - const string: "string" = "string" - const number: "number" = "number" - const boolean: "boolean" = "boolean" - - const stringOrNumber = string || number; - const stringOrBoolean = string || boolean; - const booleanOrNumber = number || boolean; - const stringOrBooleanOrNumber = stringOrBoolean || number; - - namespace Consts2 { - const EMPTY_STRING = getFalsyPrimitive(string); - const ZERO = getFalsyPrimitive(number); - const FALSE = getFalsyPrimitive(boolean); - - const a = getFalsyPrimitive(stringOrNumber); - const b = getFalsyPrimitive(stringOrBoolean); - const c = getFalsyPrimitive(booleanOrNumber); - const d = getFalsyPrimitive(stringOrBooleanOrNumber); - } - - - \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.symbols b/tests/baselines/reference/stringLiteralTypesOverloads01.symbols new file mode 100644 index 00000000000..c92fe134076 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads01.symbols @@ -0,0 +1,144 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts === + +type PrimitiveName = 'string' | 'number' | 'boolean'; +>PrimitiveName : Symbol(PrimitiveName, Decl(stringLiteralTypesOverloads01.ts, 0, 0)) + +function getFalsyPrimitive(x: "string"): string; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 3, 27)) + +function getFalsyPrimitive(x: "number"): number; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 4, 27)) + +function getFalsyPrimitive(x: "boolean"): boolean; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 5, 27)) + +function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 6, 27)) + +function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 7, 27)) + +function getFalsyPrimitive(x: "number" | "string"): number | string; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 8, 27)) + +function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 9, 27)) + +function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 10, 27)) +>PrimitiveName : Symbol(PrimitiveName, Decl(stringLiteralTypesOverloads01.ts, 0, 0)) + + if (x === "string") { +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 10, 27)) + + return ""; + } + if (x === "number") { +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 10, 27)) + + return 0; + } + if (x === "boolean") { +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 10, 27)) + + return false; + } + + // Should be unreachable. + throw "Invalid value"; +} + +namespace Consts1 { +>Consts1 : Symbol(Consts1, Decl(stringLiteralTypesOverloads01.ts, 23, 1)) + + const EMPTY_STRING = getFalsyPrimitive("string"); +>EMPTY_STRING : Symbol(EMPTY_STRING, Decl(stringLiteralTypesOverloads01.ts, 26, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) + + const ZERO = getFalsyPrimitive('number'); +>ZERO : Symbol(ZERO, Decl(stringLiteralTypesOverloads01.ts, 27, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) + + const FALSE = getFalsyPrimitive("boolean"); +>FALSE : Symbol(FALSE, Decl(stringLiteralTypesOverloads01.ts, 28, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +} + +const string: "string" = "string" +>string : Symbol(string, Decl(stringLiteralTypesOverloads01.ts, 31, 5)) + +const number: "number" = "number" +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) + +const boolean: "boolean" = "boolean" +>boolean : Symbol(boolean, Decl(stringLiteralTypesOverloads01.ts, 33, 5)) + +const stringOrNumber = string || number; +>stringOrNumber : Symbol(stringOrNumber, Decl(stringLiteralTypesOverloads01.ts, 35, 5)) +>string : Symbol(string, Decl(stringLiteralTypesOverloads01.ts, 31, 5)) +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) + +const stringOrBoolean = string || boolean; +>stringOrBoolean : Symbol(stringOrBoolean, Decl(stringLiteralTypesOverloads01.ts, 36, 5)) +>string : Symbol(string, Decl(stringLiteralTypesOverloads01.ts, 31, 5)) +>boolean : Symbol(boolean, Decl(stringLiteralTypesOverloads01.ts, 33, 5)) + +const booleanOrNumber = number || boolean; +>booleanOrNumber : Symbol(booleanOrNumber, Decl(stringLiteralTypesOverloads01.ts, 37, 5)) +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) +>boolean : Symbol(boolean, Decl(stringLiteralTypesOverloads01.ts, 33, 5)) + +const stringOrBooleanOrNumber = stringOrBoolean || number; +>stringOrBooleanOrNumber : Symbol(stringOrBooleanOrNumber, Decl(stringLiteralTypesOverloads01.ts, 38, 5)) +>stringOrBoolean : Symbol(stringOrBoolean, Decl(stringLiteralTypesOverloads01.ts, 36, 5)) +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) + +namespace Consts2 { +>Consts2 : Symbol(Consts2, Decl(stringLiteralTypesOverloads01.ts, 38, 58)) + + const EMPTY_STRING = getFalsyPrimitive(string); +>EMPTY_STRING : Symbol(EMPTY_STRING, Decl(stringLiteralTypesOverloads01.ts, 41, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>string : Symbol(string, Decl(stringLiteralTypesOverloads01.ts, 31, 5)) + + const ZERO = getFalsyPrimitive(number); +>ZERO : Symbol(ZERO, Decl(stringLiteralTypesOverloads01.ts, 42, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) + + const FALSE = getFalsyPrimitive(boolean); +>FALSE : Symbol(FALSE, Decl(stringLiteralTypesOverloads01.ts, 43, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>boolean : Symbol(boolean, Decl(stringLiteralTypesOverloads01.ts, 33, 5)) + + const a = getFalsyPrimitive(stringOrNumber); +>a : Symbol(a, Decl(stringLiteralTypesOverloads01.ts, 45, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>stringOrNumber : Symbol(stringOrNumber, Decl(stringLiteralTypesOverloads01.ts, 35, 5)) + + const b = getFalsyPrimitive(stringOrBoolean); +>b : Symbol(b, Decl(stringLiteralTypesOverloads01.ts, 46, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>stringOrBoolean : Symbol(stringOrBoolean, Decl(stringLiteralTypesOverloads01.ts, 36, 5)) + + const c = getFalsyPrimitive(booleanOrNumber); +>c : Symbol(c, Decl(stringLiteralTypesOverloads01.ts, 47, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>booleanOrNumber : Symbol(booleanOrNumber, Decl(stringLiteralTypesOverloads01.ts, 37, 5)) + + const d = getFalsyPrimitive(stringOrBooleanOrNumber); +>d : Symbol(d, Decl(stringLiteralTypesOverloads01.ts, 48, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>stringOrBooleanOrNumber : Symbol(stringOrBooleanOrNumber, Decl(stringLiteralTypesOverloads01.ts, 38, 5)) +} + + + diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.types b/tests/baselines/reference/stringLiteralTypesOverloads01.types new file mode 100644 index 00000000000..6ba8d482117 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads01.types @@ -0,0 +1,174 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts === + +type PrimitiveName = 'string' | 'number' | 'boolean'; +>PrimitiveName : "string" | "number" | "boolean" + +function getFalsyPrimitive(x: "string"): string; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "string" + +function getFalsyPrimitive(x: "number"): number; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "number" + +function getFalsyPrimitive(x: "boolean"): boolean; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "boolean" + +function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "boolean" | "string" + +function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "boolean" | "number" + +function getFalsyPrimitive(x: "number" | "string"): number | string; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "number" | "string" + +function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "number" | "string" | "boolean" + +function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "string" | "number" | "boolean" +>PrimitiveName : "string" | "number" | "boolean" + + if (x === "string") { +>x === "string" : boolean +>x : "string" | "number" | "boolean" +>"string" : string + + return ""; +>"" : string + } + if (x === "number") { +>x === "number" : boolean +>x : "string" | "number" | "boolean" +>"number" : string + + return 0; +>0 : number + } + if (x === "boolean") { +>x === "boolean" : boolean +>x : "string" | "number" | "boolean" +>"boolean" : string + + return false; +>false : boolean + } + + // Should be unreachable. + throw "Invalid value"; +>"Invalid value" : string +} + +namespace Consts1 { +>Consts1 : typeof Consts1 + + const EMPTY_STRING = getFalsyPrimitive("string"); +>EMPTY_STRING : string +>getFalsyPrimitive("string") : string +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>"string" : "string" + + const ZERO = getFalsyPrimitive('number'); +>ZERO : number +>getFalsyPrimitive('number') : number +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>'number' : "number" + + const FALSE = getFalsyPrimitive("boolean"); +>FALSE : boolean +>getFalsyPrimitive("boolean") : boolean +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>"boolean" : "boolean" +} + +const string: "string" = "string" +>string : "string" +>"string" : "string" + +const number: "number" = "number" +>number : "number" +>"number" : "number" + +const boolean: "boolean" = "boolean" +>boolean : "boolean" +>"boolean" : "boolean" + +const stringOrNumber = string || number; +>stringOrNumber : "string" | "number" +>string || number : "string" | "number" +>string : "string" +>number : "number" + +const stringOrBoolean = string || boolean; +>stringOrBoolean : "string" | "boolean" +>string || boolean : "string" | "boolean" +>string : "string" +>boolean : "boolean" + +const booleanOrNumber = number || boolean; +>booleanOrNumber : "number" | "boolean" +>number || boolean : "number" | "boolean" +>number : "number" +>boolean : "boolean" + +const stringOrBooleanOrNumber = stringOrBoolean || number; +>stringOrBooleanOrNumber : "string" | "boolean" | "number" +>stringOrBoolean || number : "string" | "boolean" | "number" +>stringOrBoolean : "string" | "boolean" +>number : "number" + +namespace Consts2 { +>Consts2 : typeof Consts2 + + const EMPTY_STRING = getFalsyPrimitive(string); +>EMPTY_STRING : string +>getFalsyPrimitive(string) : string +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>string : "string" + + const ZERO = getFalsyPrimitive(number); +>ZERO : number +>getFalsyPrimitive(number) : number +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>number : "number" + + const FALSE = getFalsyPrimitive(boolean); +>FALSE : boolean +>getFalsyPrimitive(boolean) : boolean +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>boolean : "boolean" + + const a = getFalsyPrimitive(stringOrNumber); +>a : number | string +>getFalsyPrimitive(stringOrNumber) : number | string +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>stringOrNumber : "string" | "number" + + const b = getFalsyPrimitive(stringOrBoolean); +>b : boolean | string +>getFalsyPrimitive(stringOrBoolean) : boolean | string +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>stringOrBoolean : "string" | "boolean" + + const c = getFalsyPrimitive(booleanOrNumber); +>c : boolean | number +>getFalsyPrimitive(booleanOrNumber) : boolean | number +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>booleanOrNumber : "number" | "boolean" + + const d = getFalsyPrimitive(stringOrBooleanOrNumber); +>d : number | string | boolean +>getFalsyPrimitive(stringOrBooleanOrNumber) : number | string | boolean +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>stringOrBooleanOrNumber : "string" | "boolean" | "number" +} + + + From e9dc011080e274e39f6eeecc27b5534b842739c3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 14:10:12 -0800 Subject: [PATCH 09/24] Fixed unnecessary error in test. --- .../types/stringLiteral/stringLiteralTypesAsTags01.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts index cea04f0818e..ba189406533 100644 --- a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts @@ -20,7 +20,7 @@ function hasKind(entity: Entity, kind: "A"): entity is A; function hasKind(entity: Entity, kind: "B"): entity is B; function hasKind(entity: Entity, kind: Kind): entity is Entity; function hasKind(entity: Entity, kind: Kind): boolean { - return kind === is; + return entity.kind === kind; } let x: A = { From 8cceedd725a848e9e65002b1d4871cb54c579fb9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 14:11:45 -0800 Subject: [PATCH 10/24] Accepted baselines. --- .../stringLiteralTypesAsTags01.errors.txt | 51 -------- .../reference/stringLiteralTypesAsTags01.js | 4 +- .../stringLiteralTypesAsTags01.symbols | 112 ++++++++++++++++ .../stringLiteralTypesAsTags01.types | 121 ++++++++++++++++++ .../reference/superPropertyAccess_ES5.js | 8 +- 5 files changed, 239 insertions(+), 57 deletions(-) delete mode 100644 tests/baselines/reference/stringLiteralTypesAsTags01.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags01.types diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.errors.txt b/tests/baselines/reference/stringLiteralTypesAsTags01.errors.txt deleted file mode 100644 index 90c8c3efdf7..00000000000 --- a/tests/baselines/reference/stringLiteralTypesAsTags01.errors.txt +++ /dev/null @@ -1,51 +0,0 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(20,10): error TS2394: Overload signature is not compatible with function implementation. -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(22,21): error TS2304: Cannot find name 'is'. - - -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts (2 errors) ==== - - type Kind = "A" | "B" - - interface Entity { - kind: Kind; - } - - interface A extends Entity { - kind: "A"; - a: number; - } - - interface B extends Entity { - kind: "B"; - b: string; - } - - function hasKind(entity: Entity, kind: "A"): entity is A; - function hasKind(entity: Entity, kind: "B"): entity is B; - function hasKind(entity: Entity, kind: Kind): entity is Entity; - ~~~~~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function hasKind(entity: Entity, kind: Kind): boolean { - return kind === is; - ~~ -!!! error TS2304: Cannot find name 'is'. - } - - let x: A = { - kind: "A", - a: 100, - } - - if (hasKind(x, "A")) { - let a = x; - } - else { - let b = x; - } - - if (!hasKind(x, "B")) { - let c = x; - } - else { - let d = x; - } \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.js b/tests/baselines/reference/stringLiteralTypesAsTags01.js index 3fe33ace487..b7b3872ce66 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTags01.js +++ b/tests/baselines/reference/stringLiteralTypesAsTags01.js @@ -20,7 +20,7 @@ function hasKind(entity: Entity, kind: "A"): entity is A; function hasKind(entity: Entity, kind: "B"): entity is B; function hasKind(entity: Entity, kind: Kind): entity is Entity; function hasKind(entity: Entity, kind: Kind): boolean { - return kind === is; + return entity.kind === kind; } let x: A = { @@ -44,7 +44,7 @@ else { //// [stringLiteralTypesAsTags01.js] function hasKind(entity, kind) { - return kind === is; + return entity.kind === kind; } var x = { kind: "A", diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.symbols b/tests/baselines/reference/stringLiteralTypesAsTags01.symbols new file mode 100644 index 00000000000..afdeeff71a6 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags01.symbols @@ -0,0 +1,112 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts === + +type Kind = "A" | "B" +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags01.ts, 0, 0)) + +interface Entity { +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) + + kind: Kind; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 3, 18)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags01.ts, 0, 0)) +} + +interface A extends Entity { +>A : Symbol(A, Decl(stringLiteralTypesAsTags01.ts, 5, 1)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) + + kind: "A"; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 7, 28)) + + a: number; +>a : Symbol(a, Decl(stringLiteralTypesAsTags01.ts, 8, 14)) +} + +interface B extends Entity { +>B : Symbol(B, Decl(stringLiteralTypesAsTags01.ts, 10, 1)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) + + kind: "B"; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 12, 28)) + + b: string; +>b : Symbol(b, Decl(stringLiteralTypesAsTags01.ts, 13, 14)) +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 17, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 17, 32)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 17, 17)) +>A : Symbol(A, Decl(stringLiteralTypesAsTags01.ts, 5, 1)) + +function hasKind(entity: Entity, kind: "B"): entity is B; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 18, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 18, 32)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 18, 17)) +>B : Symbol(B, Decl(stringLiteralTypesAsTags01.ts, 10, 1)) + +function hasKind(entity: Entity, kind: Kind): entity is Entity; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 19, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 19, 32)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags01.ts, 0, 0)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 19, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) + +function hasKind(entity: Entity, kind: Kind): boolean { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 20, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 20, 32)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags01.ts, 0, 0)) + + return entity.kind === kind; +>entity.kind : Symbol(Entity.kind, Decl(stringLiteralTypesAsTags01.ts, 3, 18)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 20, 17)) +>kind : Symbol(Entity.kind, Decl(stringLiteralTypesAsTags01.ts, 3, 18)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 20, 32)) +} + +let x: A = { +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +>A : Symbol(A, Decl(stringLiteralTypesAsTags01.ts, 5, 1)) + + kind: "A", +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 24, 12)) + + a: 100, +>a : Symbol(a, Decl(stringLiteralTypesAsTags01.ts, 25, 14)) +} + +if (hasKind(x, "A")) { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) + + let a = x; +>a : Symbol(a, Decl(stringLiteralTypesAsTags01.ts, 30, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +} +else { + let b = x; +>b : Symbol(b, Decl(stringLiteralTypesAsTags01.ts, 33, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +} + +if (!hasKind(x, "B")) { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) + + let c = x; +>c : Symbol(c, Decl(stringLiteralTypesAsTags01.ts, 37, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +} +else { + let d = x; +>d : Symbol(d, Decl(stringLiteralTypesAsTags01.ts, 40, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +} diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.types b/tests/baselines/reference/stringLiteralTypesAsTags01.types new file mode 100644 index 00000000000..6966ede5482 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags01.types @@ -0,0 +1,121 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts === + +type Kind = "A" | "B" +>Kind : "A" | "B" + +interface Entity { +>Entity : Entity + + kind: Kind; +>kind : "A" | "B" +>Kind : "A" | "B" +} + +interface A extends Entity { +>A : A +>Entity : Entity + + kind: "A"; +>kind : "A" + + a: number; +>a : number +} + +interface B extends Entity { +>B : B +>Entity : Entity + + kind: "B"; +>kind : "B" + + b: string; +>b : string +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>entity : Entity +>Entity : Entity +>kind : "A" +>entity : any +>A : A + +function hasKind(entity: Entity, kind: "B"): entity is B; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>entity : Entity +>Entity : Entity +>kind : "B" +>entity : any +>B : B + +function hasKind(entity: Entity, kind: Kind): entity is Entity; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>entity : Entity +>Entity : Entity +>kind : "A" | "B" +>Kind : "A" | "B" +>entity : any +>Entity : Entity + +function hasKind(entity: Entity, kind: Kind): boolean { +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>entity : Entity +>Entity : Entity +>kind : "A" | "B" +>Kind : "A" | "B" + + return entity.kind === kind; +>entity.kind === kind : boolean +>entity.kind : "A" | "B" +>entity : Entity +>kind : "A" | "B" +>kind : "A" | "B" +} + +let x: A = { +>x : A +>A : A +>{ kind: "A", a: 100,} : { kind: "A"; a: number; } + + kind: "A", +>kind : "A" +>"A" : "A" + + a: 100, +>a : number +>100 : number +} + +if (hasKind(x, "A")) { +>hasKind(x, "A") : entity is A +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>x : A +>"A" : "A" + + let a = x; +>a : A +>x : A +} +else { + let b = x; +>b : A +>x : A +} + +if (!hasKind(x, "B")) { +>!hasKind(x, "B") : boolean +>hasKind(x, "B") : entity is B +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>x : A +>"B" : "B" + + let c = x; +>c : A +>x : A +} +else { + let d = x; +>d : A +>x : A +} diff --git a/tests/baselines/reference/superPropertyAccess_ES5.js b/tests/baselines/reference/superPropertyAccess_ES5.js index a31c1dfdcba..63f5f6f316a 100644 --- a/tests/baselines/reference/superPropertyAccess_ES5.js +++ b/tests/baselines/reference/superPropertyAccess_ES5.js @@ -45,7 +45,7 @@ var MyBase = (function () { configurable: true }); return MyBase; -})(); +}()); var MyDerived = (function (_super) { __extends(MyDerived, _super); function MyDerived() { @@ -54,7 +54,7 @@ var MyDerived = (function (_super) { var f2 = _super.prototype.value; } return MyDerived; -})(MyBase); +}(MyBase)); var d = new MyDerived(); var f3 = d.value; var A = (function () { @@ -67,7 +67,7 @@ var A = (function () { configurable: true }); return A; -})(); +}()); var B = (function (_super) { __extends(B, _super); function B() { @@ -81,4 +81,4 @@ var B = (function (_super) { configurable: true }); return B; -})(A); +}(A)); From 3cdfc36109aff6243d22962f47fa331b8be84f8d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:02:43 -0800 Subject: [PATCH 11/24] Added tests for 'void' return type compatibilty on overloads and implementations. --- .../functions/functionOverloadCompatibilityWithVoid01.ts | 4 ++++ .../functions/functionOverloadCompatibilityWithVoid02.ts | 4 ++++ .../functions/functionOverloadCompatibilityWithVoid03.ts | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts create mode 100644 tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts create mode 100644 tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts diff --git a/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts new file mode 100644 index 00000000000..d973c946bb9 --- /dev/null +++ b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts @@ -0,0 +1,4 @@ +function f(x: string): number; +function f(x: string): void { + return; +} \ No newline at end of file diff --git a/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts new file mode 100644 index 00000000000..ef89d790ff7 --- /dev/null +++ b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts @@ -0,0 +1,4 @@ +function f(x: string): void; +function f(x: string): number { + return 0; +} \ No newline at end of file diff --git a/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts new file mode 100644 index 00000000000..5f0a2327d74 --- /dev/null +++ b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts @@ -0,0 +1,4 @@ +function f(x: string): void; +function f(x: string): void { + return; +} \ No newline at end of file From 069fada0ce3e15622ed2da14d9c8a3edf042bde8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:04:59 -0800 Subject: [PATCH 12/24] Accepted baselines. --- ...functionOverloadCompatibilityWithVoid01.errors.txt | 10 ++++++++++ .../functionOverloadCompatibilityWithVoid01.js | 10 ++++++++++ ...functionOverloadCompatibilityWithVoid02.errors.txt | 10 ++++++++++ .../functionOverloadCompatibilityWithVoid02.js | 10 ++++++++++ .../functionOverloadCompatibilityWithVoid03.js | 10 ++++++++++ .../functionOverloadCompatibilityWithVoid03.symbols | 11 +++++++++++ .../functionOverloadCompatibilityWithVoid03.types | 11 +++++++++++ 7 files changed, 72 insertions(+) create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid01.errors.txt create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid01.js create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.js create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid03.js create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid03.symbols create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid03.types diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.errors.txt b/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.errors.txt new file mode 100644 index 00000000000..56951e380e4 --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. + + +==== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts (1 errors) ==== + function f(x: string): number; + ~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function f(x: string): void { + return; + } \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.js b/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.js new file mode 100644 index 00000000000..b2d7e64d58e --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.js @@ -0,0 +1,10 @@ +//// [functionOverloadCompatibilityWithVoid01.ts] +function f(x: string): number; +function f(x: string): void { + return; +} + +//// [functionOverloadCompatibilityWithVoid01.js] +function f(x) { + return; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt new file mode 100644 index 00000000000..33155afb5f5 --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. + + +==== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts (1 errors) ==== + function f(x: string): void; + ~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function f(x: string): number { + return 0; + } \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.js b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.js new file mode 100644 index 00000000000..4f53be1f9c3 --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.js @@ -0,0 +1,10 @@ +//// [functionOverloadCompatibilityWithVoid02.ts] +function f(x: string): void; +function f(x: string): number { + return 0; +} + +//// [functionOverloadCompatibilityWithVoid02.js] +function f(x) { + return 0; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.js b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.js new file mode 100644 index 00000000000..b83939442cb --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.js @@ -0,0 +1,10 @@ +//// [functionOverloadCompatibilityWithVoid03.ts] +function f(x: string): void; +function f(x: string): void { + return; +} + +//// [functionOverloadCompatibilityWithVoid03.js] +function f(x) { + return; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.symbols b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.symbols new file mode 100644 index 00000000000..57fe6006ced --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts === +function f(x: string): void; +>f : Symbol(f, Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 0), Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 28)) +>x : Symbol(x, Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 11)) + +function f(x: string): void { +>f : Symbol(f, Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 0), Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 28)) +>x : Symbol(x, Decl(functionOverloadCompatibilityWithVoid03.ts, 1, 11)) + + return; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.types b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.types new file mode 100644 index 00000000000..74dfa28c142 --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts === +function f(x: string): void; +>f : (x: string) => void +>x : string + +function f(x: string): void { +>f : (x: string) => void +>x : string + + return; +} From 9b507b7512290b28bcd710a363f7a98be261a077 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:08:30 -0800 Subject: [PATCH 13/24] Specifically test for 'void' to permit implementations to return more than what was guaranteed. --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac8a4ac89a4..a83c1027ad1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4987,7 +4987,8 @@ namespace ts { const sourceReturnType = getReturnTypeOfSignature(erasedSource); const targetReturnType = getReturnTypeOfSignature(erasedTarget); - if (checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined) + if (targetReturnType === voidType + || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined) || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined)) { const anyReturningSource = cloneSignature(erasedSource); const anyReturningTarget = cloneSignature(erasedTarget); From e012645309eadc7496b26380edf49acff044fe93 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:08:45 -0800 Subject: [PATCH 14/24] Accepted baselines. --- ...unctionOverloadCompatibilityWithVoid02.errors.txt | 10 ---------- .../functionOverloadCompatibilityWithVoid02.symbols | 11 +++++++++++ .../functionOverloadCompatibilityWithVoid02.types | 12 ++++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) delete mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.symbols create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.types diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt deleted file mode 100644 index 33155afb5f5..00000000000 --- a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts (1 errors) ==== - function f(x: string): void; - ~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function f(x: string): number { - return 0; - } \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.symbols b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.symbols new file mode 100644 index 00000000000..210f7e3e4ee --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts === +function f(x: string): void; +>f : Symbol(f, Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 0), Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 28)) +>x : Symbol(x, Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 11)) + +function f(x: string): number { +>f : Symbol(f, Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 0), Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 28)) +>x : Symbol(x, Decl(functionOverloadCompatibilityWithVoid02.ts, 1, 11)) + + return 0; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.types b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.types new file mode 100644 index 00000000000..aa6fda7222b --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts === +function f(x: string): void; +>f : (x: string) => void +>x : string + +function f(x: string): number { +>f : (x: string) => void +>x : string + + return 0; +>0 : number +} From a236461358691e9773ef02b61e3ef5fa4cc79f25 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:10:50 -0800 Subject: [PATCH 15/24] Reversed order of checks, since the implementation will typically be more general than the overload. --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a83c1027ad1..cd95267589b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4988,8 +4988,8 @@ namespace ts { const sourceReturnType = getReturnTypeOfSignature(erasedSource); const targetReturnType = getReturnTypeOfSignature(erasedTarget); if (targetReturnType === voidType - || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined) - || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined)) { + || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined) + || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined)) { const anyReturningSource = cloneSignature(erasedSource); const anyReturningTarget = cloneSignature(erasedTarget); anyReturningSource.resolvedReturnType = anyType; From 73526cf39ab2086f25e3f7157edeee0897a47973 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 16:01:42 -0800 Subject: [PATCH 16/24] Do some caching so that we don't repeat the same work for the implementation signature for every overload. --- src/compiler/checker.ts | 21 +++++++++++++++++---- src/compiler/types.ts | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cd95267589b..fac21177aae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4115,6 +4115,16 @@ namespace ts { return signature.erasedSignatureCache; } + function getAnyReturningErasedSignature(signature: Signature): Signature { + if (!signature.anyReturningErasedSignatureCache) { + const erasedSignature = getErasedSignature(signature); + const anyReturningErasedSignature = cloneSignature(erasedSignature); + anyReturningErasedSignature.resolvedReturnType = anyType; + signature.anyReturningErasedSignatureCache = anyReturningErasedSignature; + } + return signature.anyReturningErasedSignatureCache; + } + function getOrCreateTypeFromSignature(signature: Signature): ObjectType { // There are two ways to declare a construct signature, one is by declaring a class constructor // using the constructor keyword, and the other is declaring a bare construct signature in an @@ -4985,16 +4995,19 @@ namespace ts { const erasedSource = getErasedSignature(implementation); const erasedTarget = getErasedSignature(overload); + // First see if the return types are compatible in either direction. const sourceReturnType = getReturnTypeOfSignature(erasedSource); const targetReturnType = getReturnTypeOfSignature(erasedTarget); if (targetReturnType === voidType || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined) || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined)) { - const anyReturningSource = cloneSignature(erasedSource); - const anyReturningTarget = cloneSignature(erasedTarget); - anyReturningSource.resolvedReturnType = anyType; - anyReturningTarget.resolvedReturnType = anyType; + // The return types are compatible, so create versions of the signature with 'any' as the return type. + // We need to do this so that we can check assignability while disregarding the return type. + const anyReturningSource = getAnyReturningErasedSignature(implementation); + const anyReturningTarget = getAnyReturningErasedSignature(overload); + + // Create object types to actually perform relation checks. const anyReturningSourceType = getOrCreateTypeFromSignature(anyReturningSource); const anyReturningTargetType = getOrCreateTypeFromSignature(anyReturningTarget); return checkTypeRelatedTo(anyReturningSourceType, anyReturningTargetType, assignableRelation, /*errorNode*/ undefined); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ff8ffa4ebd2..c6c78709300 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2280,6 +2280,8 @@ namespace ts { /* @internal */ erasedSignatureCache?: Signature; // Erased version of signature (deferred) /* @internal */ + anyReturningErasedSignatureCache?: Signature; // A version of the erased signature whose type returns 'any' + /* @internal */ isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison } From 5cbf17d989d6f746de480631fa6b05d43d1afd8f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 14 Dec 2015 14:16:31 -0800 Subject: [PATCH 17/24] Added tests. --- .../stringLiteralTypesAsTags02.ts | 42 +++++++++++++++++ .../stringLiteralTypesAsTags03.ts | 46 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts new file mode 100644 index 00000000000..9fdc942a3f2 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts @@ -0,0 +1,42 @@ +// @declaration: true + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +function hasKind(entity: Entity, kind: "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is (A | B) { + return entity.kind === kind; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts new file mode 100644 index 00000000000..96011d27255 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts @@ -0,0 +1,46 @@ +// @declaration: true + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +// Currently (2015-12-14), we write '"A" | "A"' and '"B" | "B"' to avoid +// interpreting respective overloads as "specialized" signatures. +// That way, we can avoid the need to look for a compatible overload +// signature and simply check compatibility with the implementation. +function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is Entity { + return entity.kind === kind; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} \ No newline at end of file From 2efa69773d5e7fb208e2a03e52758189e058d266 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 14 Dec 2015 14:24:55 -0800 Subject: [PATCH 18/24] Accepted baselines. --- .../stringLiteralTypesAsTags02.errors.txt | 50 ++++++++ .../reference/stringLiteralTypesAsTags02.js | 81 ++++++++++++ .../reference/stringLiteralTypesAsTags03.js | 85 +++++++++++++ .../stringLiteralTypesAsTags03.symbols | 109 ++++++++++++++++ .../stringLiteralTypesAsTags03.types | 118 ++++++++++++++++++ 5 files changed, 443 insertions(+) create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags02.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags02.js create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags03.js create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags03.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags03.types diff --git a/tests/baselines/reference/stringLiteralTypesAsTags02.errors.txt b/tests/baselines/reference/stringLiteralTypesAsTags02.errors.txt new file mode 100644 index 00000000000..077113632d0 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags02.errors.txt @@ -0,0 +1,50 @@ +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts(18,10): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts(19,10): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + + +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts (2 errors) ==== + + type Kind = "A" | "B" + + interface Entity { + kind: Kind; + } + + interface A extends Entity { + kind: "A"; + a: number; + } + + interface B extends Entity { + kind: "B"; + b: string; + } + + function hasKind(entity: Entity, kind: "A"): entity is A; + ~~~~~~~ +!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + function hasKind(entity: Entity, kind: "B"): entity is B; + ~~~~~~~ +!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + function hasKind(entity: Entity, kind: Kind): entity is (A | B) { + return entity.kind === kind; + } + + let x: A = { + kind: "A", + a: 100, + } + + if (hasKind(x, "A")) { + let a = x; + } + else { + let b = x; + } + + if (!hasKind(x, "B")) { + let c = x; + } + else { + let d = x; + } \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAsTags02.js b/tests/baselines/reference/stringLiteralTypesAsTags02.js new file mode 100644 index 00000000000..e83f1ad46ee --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags02.js @@ -0,0 +1,81 @@ +//// [stringLiteralTypesAsTags02.ts] + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +function hasKind(entity: Entity, kind: "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is (A | B) { + return entity.kind === kind; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} + +//// [stringLiteralTypesAsTags02.js] +function hasKind(entity, kind) { + return entity.kind === kind; +} +var x = { + kind: "A", + a: 100 +}; +if (hasKind(x, "A")) { + var a = x; +} +else { + var b = x; +} +if (!hasKind(x, "B")) { + var c = x; +} +else { + var d = x; +} + + +//// [stringLiteralTypesAsTags02.d.ts] +declare type Kind = "A" | "B"; +interface Entity { + kind: Kind; +} +interface A extends Entity { + kind: "A"; + a: number; +} +interface B extends Entity { + kind: "B"; + b: string; +} +declare function hasKind(entity: Entity, kind: "A"): entity is A; +declare function hasKind(entity: Entity, kind: "B"): entity is B; +declare let x: A; diff --git a/tests/baselines/reference/stringLiteralTypesAsTags03.js b/tests/baselines/reference/stringLiteralTypesAsTags03.js new file mode 100644 index 00000000000..bb2ed56040e --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags03.js @@ -0,0 +1,85 @@ +//// [stringLiteralTypesAsTags03.ts] + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +// Currently (2015-12-14), we write '"A" | "A"' and '"B" | "B"' to avoid +// interpreting respective overloads as "specialized" signatures. +// That way, we can avoid the need to look for a compatible overload +// signature and simply check compatibility with the implementation. +function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is Entity { + return entity.kind === kind; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} + +//// [stringLiteralTypesAsTags03.js] +function hasKind(entity, kind) { + return entity.kind === kind; +} +var x = { + kind: "A", + a: 100 +}; +if (hasKind(x, "A")) { + var a = x; +} +else { + var b = x; +} +if (!hasKind(x, "B")) { + var c = x; +} +else { + var d = x; +} + + +//// [stringLiteralTypesAsTags03.d.ts] +declare type Kind = "A" | "B"; +interface Entity { + kind: Kind; +} +interface A extends Entity { + kind: "A"; + a: number; +} +interface B extends Entity { + kind: "B"; + b: string; +} +declare function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +declare function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +declare let x: A; diff --git a/tests/baselines/reference/stringLiteralTypesAsTags03.symbols b/tests/baselines/reference/stringLiteralTypesAsTags03.symbols new file mode 100644 index 00000000000..3694daf8e00 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags03.symbols @@ -0,0 +1,109 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts === + +type Kind = "A" | "B" +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags03.ts, 0, 0)) + +interface Entity { +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) + + kind: Kind; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 3, 18)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags03.ts, 0, 0)) +} + +interface A extends Entity { +>A : Symbol(A, Decl(stringLiteralTypesAsTags03.ts, 5, 1)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) + + kind: "A"; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 7, 28)) + + a: number; +>a : Symbol(a, Decl(stringLiteralTypesAsTags03.ts, 8, 14)) +} + +interface B extends Entity { +>B : Symbol(B, Decl(stringLiteralTypesAsTags03.ts, 10, 1)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) + + kind: "B"; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 12, 28)) + + b: string; +>b : Symbol(b, Decl(stringLiteralTypesAsTags03.ts, 13, 14)) +} + +// Currently (2015-12-14), we write '"A" | "A"' and '"B" | "B"' to avoid +// interpreting respective overloads as "specialized" signatures. +// That way, we can avoid the need to look for a compatible overload +// signature and simply check compatibility with the implementation. +function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 21, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 21, 32)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 21, 17)) +>A : Symbol(A, Decl(stringLiteralTypesAsTags03.ts, 5, 1)) + +function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 22, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 22, 32)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 22, 17)) +>B : Symbol(B, Decl(stringLiteralTypesAsTags03.ts, 10, 1)) + +function hasKind(entity: Entity, kind: Kind): entity is Entity { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 23, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 23, 32)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags03.ts, 0, 0)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 23, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) + + return entity.kind === kind; +>entity.kind : Symbol(Entity.kind, Decl(stringLiteralTypesAsTags03.ts, 3, 18)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 23, 17)) +>kind : Symbol(Entity.kind, Decl(stringLiteralTypesAsTags03.ts, 3, 18)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 23, 32)) +} + +let x: A = { +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +>A : Symbol(A, Decl(stringLiteralTypesAsTags03.ts, 5, 1)) + + kind: "A", +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 27, 12)) + + a: 100, +>a : Symbol(a, Decl(stringLiteralTypesAsTags03.ts, 28, 14)) +} + +if (hasKind(x, "A")) { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) + + let a = x; +>a : Symbol(a, Decl(stringLiteralTypesAsTags03.ts, 33, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +} +else { + let b = x; +>b : Symbol(b, Decl(stringLiteralTypesAsTags03.ts, 36, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +} + +if (!hasKind(x, "B")) { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) + + let c = x; +>c : Symbol(c, Decl(stringLiteralTypesAsTags03.ts, 40, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +} +else { + let d = x; +>d : Symbol(d, Decl(stringLiteralTypesAsTags03.ts, 43, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +} diff --git a/tests/baselines/reference/stringLiteralTypesAsTags03.types b/tests/baselines/reference/stringLiteralTypesAsTags03.types new file mode 100644 index 00000000000..a1d83a1c058 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags03.types @@ -0,0 +1,118 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts === + +type Kind = "A" | "B" +>Kind : "A" | "B" + +interface Entity { +>Entity : Entity + + kind: Kind; +>kind : "A" | "B" +>Kind : "A" | "B" +} + +interface A extends Entity { +>A : A +>Entity : Entity + + kind: "A"; +>kind : "A" + + a: number; +>a : number +} + +interface B extends Entity { +>B : B +>Entity : Entity + + kind: "B"; +>kind : "B" + + b: string; +>b : string +} + +// Currently (2015-12-14), we write '"A" | "A"' and '"B" | "B"' to avoid +// interpreting respective overloads as "specialized" signatures. +// That way, we can avoid the need to look for a compatible overload +// signature and simply check compatibility with the implementation. +function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>entity : Entity +>Entity : Entity +>kind : "A" +>entity : any +>A : A + +function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>entity : Entity +>Entity : Entity +>kind : "B" +>entity : any +>B : B + +function hasKind(entity: Entity, kind: Kind): entity is Entity { +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>entity : Entity +>Entity : Entity +>kind : "A" | "B" +>Kind : "A" | "B" +>entity : any +>Entity : Entity + + return entity.kind === kind; +>entity.kind === kind : boolean +>entity.kind : "A" | "B" +>entity : Entity +>kind : "A" | "B" +>kind : "A" | "B" +} + +let x: A = { +>x : A +>A : A +>{ kind: "A", a: 100,} : { kind: "A"; a: number; } + + kind: "A", +>kind : "A" +>"A" : "A" + + a: 100, +>a : number +>100 : number +} + +if (hasKind(x, "A")) { +>hasKind(x, "A") : entity is A +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>x : A +>"A" : "A" + + let a = x; +>a : A +>x : A +} +else { + let b = x; +>b : A +>x : A +} + +if (!hasKind(x, "B")) { +>!hasKind(x, "B") : boolean +>hasKind(x, "B") : entity is B +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>x : A +>"B" : "B" + + let c = x; +>c : A +>x : A +} +else { + let d = x; +>d : A +>x : A +} From 023e375835886c77278328663c79bf010f8f836e Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 14 Dec 2015 16:44:26 -0800 Subject: [PATCH 19/24] Properly handle multiply-declared optional properties in JSX attr. type Fixes #6029 --- src/compiler/checker.ts | 15 +++++-- src/compiler/diagnosticMessages.json | 2 +- .../tsxAttributeResolution11.errors.txt | 33 +++++++++++++++ .../reference/tsxAttributeResolution11.js | 41 +++++++++++++++++++ .../jsx/tsxAttributeResolution11.tsx | 29 +++++++++++++ 5 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/tsxAttributeResolution11.errors.txt create mode 100644 tests/baselines/reference/tsxAttributeResolution11.js create mode 100644 tests/cases/conformance/jsx/tsxAttributeResolution11.tsx diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 78a7ccffbdd..09760b6b1e5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3766,11 +3766,13 @@ namespace ts { function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol { const types = containingType.types; let props: Symbol[]; + let isOptional = !!(containingType.flags & TypeFlags.Intersection); for (const current of types) { const type = getApparentType(current); if (type !== unknownType) { const prop = getPropertyOfType(type, name); if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) { + isOptional = isOptional && !!(prop.flags & SymbolFlags.Optional); if (!props) { props = [prop]; } @@ -3798,7 +3800,12 @@ namespace ts { } propTypes.push(getTypeOfSymbol(prop)); } - const result = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty, name); + const result = createSymbol( + SymbolFlags.Property | + SymbolFlags.Transient | + SymbolFlags.SyntheticProperty | + (isOptional ? SymbolFlags.Optional : SymbolFlags.None), + name); result.containingType = containingType; result.declarations = declarations; result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes); @@ -8232,9 +8239,9 @@ namespace ts { // Props is of type 'any' or unknown return links.resolvedJsxType = attributesType; } - else if (!(attributesType.flags & TypeFlags.ObjectType)) { - // Props is not an object type - error(node.tagName, Diagnostics.JSX_element_attributes_type_0_must_be_an_object_type, typeToString(attributesType)); + else if (attributesType.flags & TypeFlags.Union) { + // Props cannot be a union type + error(node.tagName, Diagnostics.JSX_element_attributes_type_0_may_not_be_a_union_type, typeToString(attributesType)); return links.resolvedJsxType = anyType; } else { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 54123808932..1a2575e9da6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1691,7 +1691,7 @@ "category": "Error", "code": 2528 }, - "JSX element attributes type '{0}' must be an object type.": { + "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 }, diff --git a/tests/baselines/reference/tsxAttributeResolution11.errors.txt b/tests/baselines/reference/tsxAttributeResolution11.errors.txt new file mode 100644 index 00000000000..b043897d50d --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution11.errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/jsx/file.tsx(11,22): error TS2339: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'. + + +==== tests/cases/conformance/jsx/react.d.ts (0 errors) ==== + + declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } + interface IntrinsicAttributes { + ref?: string; + } + } + +==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== + class MyComponent { + render() { + } + + props: { + ref?: string; + } + } + + // Should be an OK + var x = ; + ~~~ +!!! error TS2339: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'. + + \ No newline at end of file diff --git a/tests/baselines/reference/tsxAttributeResolution11.js b/tests/baselines/reference/tsxAttributeResolution11.js new file mode 100644 index 00000000000..03b843c209a --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution11.js @@ -0,0 +1,41 @@ +//// [tests/cases/conformance/jsx/tsxAttributeResolution11.tsx] //// + +//// [react.d.ts] + +declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } + interface IntrinsicAttributes { + ref?: string; + } +} + +//// [file.tsx] +class MyComponent { + render() { + } + + props: { + ref?: string; + } +} + +// Should be an OK +var x = ; + + + +//// [file.jsx] +var MyComponent = (function () { + function MyComponent() { + } + MyComponent.prototype.render = function () { + }; + return MyComponent; +}()); +// Should be an OK +var x = ; diff --git a/tests/cases/conformance/jsx/tsxAttributeResolution11.tsx b/tests/cases/conformance/jsx/tsxAttributeResolution11.tsx new file mode 100644 index 00000000000..fdff3c36fc7 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxAttributeResolution11.tsx @@ -0,0 +1,29 @@ +//@jsx: preserve +//@module: amd + +//@filename: react.d.ts +declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } + interface IntrinsicAttributes { + ref?: string; + } +} + +//@filename: file.tsx +class MyComponent { + render() { + } + + props: { + ref?: string; + } +} + +// Should be an OK +var x = ; + From ec95f9955af6507bba7b572ce913e48fd9639c94 Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 15 Dec 2015 10:04:30 -0800 Subject: [PATCH 20/24] Fix linting issue --- Jakefile.js | 3 +- src/services/services.ts | 1073 +++++++++++++++++++------------------- 2 files changed, 538 insertions(+), 538 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index beb16d2886f..91bd805a27b 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -924,7 +924,8 @@ function lintFileAsync(options, path, cb) { var lintTargets = compilerSources .concat(harnessCoreSources) .concat(serverCoreSources) - .concat(scriptSources); + .concat(scriptSources) + .concat([path.join(servicesDirectory,"services.ts")]); desc("Runs tslint on the compiler sources"); task("lint", ["build-rules"], function() { diff --git a/src/services/services.ts b/src/services/services.ts index a9dda549ead..8f9028486aa 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -12,7 +12,7 @@ namespace ts { /** The version of the language service API */ - export let servicesVersion = "0.4" + export const servicesVersion = "0.4"; export interface Node { getSourceFile(): SourceFile; @@ -48,7 +48,7 @@ namespace ts { getConstructSignatures(): Signature[]; getStringIndexType(): Type; getNumberIndexType(): Type; - getBaseTypes(): ObjectType[] + getBaseTypes(): ObjectType[]; } export interface Signature { @@ -97,7 +97,7 @@ namespace ts { dispose?(): void; } - export module ScriptSnapshot { + export namespace ScriptSnapshot { class StringScriptSnapshot implements IScriptSnapshot { constructor(private text: string) { @@ -126,12 +126,12 @@ namespace ts { referencedFiles: FileReference[]; importedFiles: FileReference[]; ambientExternalModules: string[]; - isLibFile: boolean + isLibFile: boolean; } - let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); + const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); - let emptyArray: any[] = []; + const emptyArray: any[] = []; const jsDocTagNames = [ "augments", @@ -174,7 +174,7 @@ namespace ts { let jsDocCompletionEntries: CompletionEntry[]; function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject { - let node = new NodeObject(kind, pos, end); + const node = new NodeObject(kind, pos, end); node.flags = flags; node.parent = parent; return node; @@ -235,8 +235,8 @@ namespace ts { private addSyntheticNodes(nodes: Node[], pos: number, end: number): number { scanner.setTextPos(pos); while (pos < end) { - let token = scanner.scan(); - let textPos = scanner.getTextPos(); + const token = scanner.scan(); + const textPos = scanner.getTextPos(); nodes.push(createNode(token, pos, textPos, NodeFlags.Synthetic, this)); pos = textPos; } @@ -244,13 +244,11 @@ namespace ts { } private createSyntaxList(nodes: NodeArray): Node { - let list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); + const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); list._children = []; let pos = nodes.pos; - - - for (let node of nodes) { + for (const node of nodes) { if (pos < node.pos) { pos = this.addSyntheticNodes(list._children, pos, node.pos); } @@ -269,14 +267,14 @@ namespace ts { scanner.setText((sourceFile || this.getSourceFile()).text); children = []; let pos = this.pos; - let processNode = (node: Node) => { + const processNode = (node: Node) => { if (pos < node.pos) { pos = this.addSyntheticNodes(children, pos, node.pos); } children.push(node); pos = node.end; }; - let processNodes = (nodes: NodeArray) => { + const processNodes = (nodes: NodeArray) => { if (pos < nodes.pos) { pos = this.addSyntheticNodes(children, pos, nodes.pos); } @@ -308,20 +306,20 @@ namespace ts { } public getFirstToken(sourceFile?: SourceFile): Node { - let children = this.getChildren(sourceFile); + const children = this.getChildren(sourceFile); if (!children.length) { return undefined; } - let child = children[0]; + const child = children[0]; return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile); } public getLastToken(sourceFile?: SourceFile): Node { - let children = this.getChildren(sourceFile); + const children = this.getChildren(sourceFile); - let child = lastOrUndefined(children); + const child = lastOrUndefined(children); if (!child) { return undefined; } @@ -366,8 +364,8 @@ namespace ts { } function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean) { - let documentationComment = []; - let docComments = getJsDocCommentsSeparatedByNewLines(); + const documentationComment = []; + const docComments = getJsDocCommentsSeparatedByNewLines(); ts.forEach(docComments, docComment => { if (documentationComment.length) { documentationComment.push(lineBreakPart()); @@ -378,22 +376,22 @@ namespace ts { return documentationComment; function getJsDocCommentsSeparatedByNewLines() { - let paramTag = "@param"; - let jsDocCommentParts: SymbolDisplayPart[] = []; + const paramTag = "@param"; + const jsDocCommentParts: SymbolDisplayPart[] = []; ts.forEach(declarations, (declaration, indexOfDeclaration) => { // Make sure we are collecting doc comment from declaration once, // In case of union property there might be same declaration multiple times // which only varies in type parameter - // Eg. let a: Array | Array; a.length + // Eg. const a: Array | Array; a.length // The property length will have two declarations of property length coming // from Array - Array and Array if (indexOf(declarations, declaration) === indexOfDeclaration) { - let sourceFileOfDeclaration = getSourceFileOfNode(declaration); + const sourceFileOfDeclaration = getSourceFileOfNode(declaration); // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments if (canUseParsedParamTagComments && declaration.kind === SyntaxKind.Parameter) { ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => { - let cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + const cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedParamJsDocComment) { addRange(jsDocCommentParts, cleanedParamJsDocComment); } @@ -413,7 +411,7 @@ namespace ts { // Get the cleaned js doc comment text from the declaration ts.forEach(getJsDocCommentTextRange( declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => { - let cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + const cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedJsDocComment) { addRange(jsDocCommentParts, cleanedJsDocComment); } @@ -439,7 +437,7 @@ namespace ts { } for (; pos < end; pos++) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); if (!isWhiteSpace(ch) || isLineBreak(ch)) { // Either found lineBreak or non whiteSpace return pos; @@ -480,7 +478,7 @@ namespace ts { function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let spacesToRemoveAfterAsterisk: number; - let docComments: SymbolDisplayPart[] = []; + const docComments: SymbolDisplayPart[] = []; let blankLineCount = 0; let isInParamTag = false; @@ -491,7 +489,7 @@ namespace ts { // If the comment starts with '*' consume the spaces on this line if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) { - let lineStartPos = pos + 1; + const lineStartPos = pos + 1; pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); // Set the spaces to remove after asterisk as margin if not already set @@ -505,7 +503,7 @@ namespace ts { // Analyse text on this line while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { - let ch = sourceFile.text.charAt(pos); + const ch = sourceFile.text.charAt(pos); if (ch === "@") { // If it is @param tag if (isParamTag(pos, end, sourceFile)) { @@ -544,7 +542,7 @@ namespace ts { function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let paramHelpStringMargin: number; - let paramDocComments: SymbolDisplayPart[] = []; + const paramDocComments: SymbolDisplayPart[] = []; while (pos < end) { if (isParamTag(pos, end, sourceFile)) { let blankLineCount = 0; @@ -559,7 +557,7 @@ namespace ts { if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) { pos++; for (let curlies = 1; pos < end; pos++) { - let charCode = sourceFile.text.charCodeAt(pos); + const charCode = sourceFile.text.charCodeAt(pos); // { character means we need to find another } to match the found one if (charCode === CharacterCodes.openBrace) { @@ -603,9 +601,9 @@ namespace ts { } let paramHelpString = ""; - let firstLineParamHelpStringPos = pos; + const firstLineParamHelpStringPos = pos; while (pos < end) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); // at line break, set this comment line text and go to next line if (isLineBreak(ch)) { @@ -674,15 +672,15 @@ namespace ts { } // Now consume white spaces max - let startOfLinePos = pos; + const startOfLinePos = pos; pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); if (pos >= end) { return; } - let consumedSpaces = pos - startOfLinePos; + const consumedSpaces = pos - startOfLinePos; if (consumedSpaces < paramHelpStringMargin) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); if (ch === CharacterCodes.asterisk) { // Consume more spaces after asterisk pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); @@ -815,7 +813,7 @@ namespace ts { private namedDeclarations: Map; constructor(kind: SyntaxKind, pos: number, end: number) { - super(kind, pos, end) + super(kind, pos, end); } public update(newText: string, textChangeRange: TextChangeRange): SourceFile { @@ -843,16 +841,16 @@ namespace ts { } private computeNamedDeclarations(): Map { - let result: Map = {}; + const result: Map = {}; forEachChild(this, visit); return result; function addDeclaration(declaration: Declaration) { - let name = getDeclarationName(declaration); + const name = getDeclarationName(declaration); if (name) { - let declarations = getDeclarations(name); + const declarations = getDeclarations(name); declarations.push(declaration); } } @@ -863,13 +861,13 @@ namespace ts { function getDeclarationName(declaration: Declaration) { if (declaration.name) { - let result = getTextOfIdentifierOrLiteral(declaration.name); + const result = getTextOfIdentifierOrLiteral(declaration.name); if (result !== undefined) { return result; } if (declaration.name.kind === SyntaxKind.ComputedPropertyName) { - let expr = (declaration.name).expression; + const expr = (declaration.name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { return (expr).name.text; } @@ -899,12 +897,12 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - let functionDeclaration = node; - let declarationName = getDeclarationName(functionDeclaration); + const functionDeclaration = node; + const declarationName = getDeclarationName(functionDeclaration); if (declarationName) { - let declarations = getDeclarations(declarationName); - let lastDeclaration = lastOrUndefined(declarations); + const declarations = getDeclarations(declarationName); + const lastDeclaration = lastOrUndefined(declarations); // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { @@ -980,7 +978,7 @@ namespace ts { break; case SyntaxKind.ImportDeclaration: - let importClause = (node).importClause; + const importClause = (node).importClause; if (importClause) { // Handle default import case e.g.: // import d from "mod"; @@ -1113,8 +1111,8 @@ namespace ts { } export interface Classifications { - spans: number[], - endOfLineState: EndOfLineState + spans: number[]; + endOfLineState: EndOfLineState; } export interface ClassifiedSpan { @@ -1171,7 +1169,7 @@ namespace ts { highlightSpans: HighlightSpan[]; } - export module HighlightSpanKind { + export namespace HighlightSpanKind { export const none = "none"; export const definition = "definition"; export const reference = "reference"; @@ -1220,7 +1218,7 @@ namespace ts { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number| string; + [s: string]: boolean | number | string; } export interface DefinitionInfo { @@ -1500,7 +1498,7 @@ namespace ts { } // TODO: move these to enums - export module ScriptElementKind { + export namespace ScriptElementKind { export const unknown = ""; export const warning = "warning"; @@ -1529,7 +1527,7 @@ namespace ts { export const enumElement = "enum"; // Inside module and script only - // let v = .. + // const v = .. export const variableElement = "var"; // Inside function @@ -1581,7 +1579,7 @@ namespace ts { export const letElement = "let"; } - export module ScriptElementKindModifier { + export namespace ScriptElementKindModifier { export const none = ""; export const publicMemberModifier = "public"; export const privateMemberModifier = "private"; @@ -1723,8 +1721,8 @@ namespace ts { this.fileNameToEntry = createFileMap(); // Initialize the list with the root file names - let rootFileNames = host.getScriptFileNames(); - for (let fileName of rootFileNames) { + const rootFileNames = host.getScriptFileNames(); + for (const fileName of rootFileNames) { this.createEntry(fileName, toPath(fileName, this.currentDirectory, getCanonicalFileName)); } @@ -1738,7 +1736,7 @@ namespace ts { private createEntry(fileName: string, path: Path) { let entry: HostFileInformation; - let scriptSnapshot = this.host.getScriptSnapshot(fileName); + const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (scriptSnapshot) { entry = { hostFileName: fileName, @@ -1760,7 +1758,7 @@ namespace ts { } public getOrCreateEntry(fileName: string): HostFileInformation { - let path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName) + const path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName); if (this.contains(path)) { return this.getEntry(path); } @@ -1769,7 +1767,7 @@ namespace ts { } public getRootFileNames(): string[] { - let fileNames: string[] = []; + const fileNames: string[] = []; this.fileNameToEntry.forEachValue((path, value) => { if (value) { @@ -1781,12 +1779,12 @@ namespace ts { } public getVersion(path: Path): string { - let file = this.getEntry(path); + const file = this.getEntry(path); return file && file.version; } public getScriptSnapshot(path: Path): IScriptSnapshot { - let file = this.getEntry(path); + const file = this.getEntry(path); return file && file.scriptSnapshot; } } @@ -1803,22 +1801,22 @@ namespace ts { } public getCurrentSourceFile(fileName: string): SourceFile { - let scriptSnapshot = this.host.getScriptSnapshot(fileName); + const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } - let version = this.host.getScriptVersion(fileName); + const version = this.host.getScriptVersion(fileName); let sourceFile: SourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. - let editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); + const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); } @@ -1863,7 +1861,7 @@ namespace ts { * - noResolve = true */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { - let options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); + const options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); options.isolatedModules = true; @@ -1879,21 +1877,22 @@ namespace ts { options.noResolve = true; // if jsx is specified then treat file as .tsx - let inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - let sourceFile = createSourceFile(inputFileName, input, options.target); + const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); + const sourceFile = createSourceFile(inputFileName, input, options.target); if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } sourceFile.renamedDependencies = transpileOptions.renamedDependencies; - let newLine = getNewLineCharacter(options); + const newLine = getNewLineCharacter(options); // Output let outputText: string; let sourceMapText: string; + // Create a compilerHost object to allow the compiler to read and write files - let compilerHost: CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: (fileName, target) => fileName === normalizeSlashes(inputFileName) ? sourceFile : undefined, writeFile: (name, text, writeByteOrderMark) => { if (fileExtensionIs(name, ".map")) { @@ -1914,7 +1913,7 @@ namespace ts { readFile: (fileName): string => "" }; - let program = createProgram([inputFileName], options, compilerHost); + const program = createProgram([inputFileName], options, compilerHost); let diagnostics: Diagnostic[]; if (transpileOptions.reportDiagnostics) { @@ -1934,15 +1933,15 @@ namespace ts { * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. */ export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string { - let output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); + const output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); // addRange correctly handles cases when wither 'from' or 'to' argument is missing addRange(diagnostics, output.diagnostics); return output.outputText; } export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile { - let text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - let sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); + const text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); + const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); setSourceFileFields(sourceFile, scriptSnapshot, version); // after full parsing we can use table with interned strings as name table sourceFile.nameTable = sourceFile.identifiers; @@ -1961,12 +1960,12 @@ namespace ts { let newText: string; // grab the fragment from the beginning of the original text to the beginning of the span - let prefix = textChangeRange.span.start !== 0 + const prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : ""; // grab the fragment from the end of the span till the end of the original text - let suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length + const suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(textSpanEnd(textChangeRange.span)) : ""; @@ -1976,7 +1975,7 @@ namespace ts { } else { // it was actual edit, fetch the fragment of new text that correspond to new span - let changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + const changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix @@ -1985,7 +1984,7 @@ namespace ts { : (changedText + suffix); } - let newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later @@ -2006,7 +2005,7 @@ namespace ts { } // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents:*/ true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); } export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { @@ -2019,15 +2018,15 @@ namespace ts { export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. - let buckets: Map> = {}; - let getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); + const buckets: Map> = {}; + const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function getKeyFromCompilationSettings(settings: CompilerOptions): string { return "_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + +"|" + settings.allowJs; } function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): FileMap { - let key = getKeyFromCompilationSettings(settings); + const key = getKeyFromCompilationSettings(settings); let bucket = lookUp(buckets, key); if (!bucket && createIfMissing) { buckets[key] = bucket = createFileMap(); @@ -2036,9 +2035,9 @@ namespace ts { } function reportStats() { - let bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === '_').map(name => { - let entries = lookUp(buckets, name); - let sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; + const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => { + const entries = lookUp(buckets, name); + const sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; entries.forEachValue((key, entry) => { sourceFiles.push({ name: key, @@ -2052,15 +2051,15 @@ namespace ts { sourceFiles }; }); - return JSON.stringify(bucketInfoArray, null, 2); + return JSON.stringify(bucketInfoArray, undefined, 2); } function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ true); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true); } function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ false); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false); } function acquireOrUpdateDocument( @@ -2070,14 +2069,14 @@ namespace ts { version: string, acquiring: boolean): SourceFile { - let bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); - let path = toPath(fileName, currentDirectory, getCanonicalFileName); + const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); let entry = bucket.get(path); if (!entry) { Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); // Have never seen this file with these settings. Create a new source file for it. - let sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false); entry = { sourceFile: sourceFile, @@ -2109,12 +2108,12 @@ namespace ts { } function releaseDocument(fileName: string, compilationSettings: CompilerOptions): void { - let bucket = getBucketForCompilationSettings(compilationSettings, false); + const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/false); Debug.assert(bucket !== undefined); - let path = toPath(fileName, currentDirectory, getCanonicalFileName); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); - let entry = bucket.get(path); + const entry = bucket.get(path); entry.languageServiceRefCount--; Debug.assert(entry.languageServiceRefCount >= 0); @@ -2132,19 +2131,19 @@ namespace ts { } export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { - let referencedFiles: FileReference[] = []; - let importedFiles: FileReference[] = []; + const referencedFiles: FileReference[] = []; + const importedFiles: FileReference[] = []; let ambientExternalModules: string[]; let isNoDefaultLib = false; function processTripleSlashDirectives(): void { - let commentRanges = getLeadingCommentRanges(sourceText, 0); + const commentRanges = getLeadingCommentRanges(sourceText, 0); forEach(commentRanges, commentRange => { - let comment = sourceText.substring(commentRange.pos, commentRange.end); - let referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); + const comment = sourceText.substring(commentRange.pos, commentRange.end); + const referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); if (referencePathMatchResult) { isNoDefaultLib = referencePathMatchResult.isNoDefaultLib; - let fileReference = referencePathMatchResult.fileReference; + const fileReference = referencePathMatchResult.fileReference; if (fileReference) { referencedFiles.push(fileReference); } @@ -2160,8 +2159,8 @@ namespace ts { } function recordModuleName() { - let importPath = scanner.getTokenValue(); - let pos = scanner.getTokenPos(); + const importPath = scanner.getTokenValue(); + const pos = scanner.getTokenPos(); importedFiles.push({ fileName: importPath, pos: pos, @@ -2213,7 +2212,7 @@ namespace ts { } } else if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -2311,7 +2310,7 @@ namespace ts { if (token === SyntaxKind.Identifier || isKeyword(token)) { token = scanner.scan(); if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -2410,7 +2409,7 @@ namespace ts { if (tryConsumeDeclare() || tryConsumeImport() || tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(/* skipCurrentToken */ false) || tryConsumeDefine()))) { + (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { continue; } else { @@ -2550,8 +2549,8 @@ namespace ts { return true; } else if (position === comment.end) { - let text = sourceFile.text; - let width = comment.end - comment.pos; + const text = sourceFile.text; + const width = comment.end - comment.pos; // is single line comment or just /* if (width <= 2 || text.charCodeAt(comment.pos + 1) === CharacterCodes.slash) { return true; @@ -2583,7 +2582,7 @@ namespace ts { } // A cache of completion entries for keywords, these do not change between sessions - let keywordCompletions: CompletionEntry[] = []; + const keywordCompletions: CompletionEntry[] = []; for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) { keywordCompletions.push({ name: tokenToString(i), @@ -2673,15 +2672,15 @@ namespace ts { export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService { - let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); + const syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); let ruleProvider: formatting.RulesProvider; let program: Program; let lastProjectVersion: string; - let useCaseSensitivefileNames = false; - let cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); + const useCaseSensitivefileNames = false; + const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); - let currentDirectory = host.getCurrentDirectory(); + const currentDirectory = host.getCurrentDirectory(); // Check if the localized messages json is set, otherwise query the host for it if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); @@ -2693,10 +2692,10 @@ namespace ts { } } - let getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); + const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); function getValidSourceFile(fileName: string): SourceFile { - let sourceFile = program.getSourceFile(fileName); + const sourceFile = program.getSourceFile(fileName); if (!sourceFile) { throw new Error("Could not find file: '" + fileName + "'."); } @@ -2716,7 +2715,7 @@ namespace ts { function synchronizeHostData(): void { // perform fast check if host supports it if (host.getProjectVersion) { - let hostProjectVersion = host.getProjectVersion(); + const hostProjectVersion = host.getProjectVersion(); if (hostProjectVersion) { if (lastProjectVersion === hostProjectVersion) { return; @@ -2740,17 +2739,17 @@ namespace ts { // the program points to old source files that have been invalidated because of // incremental parsing. - let oldSettings = program && program.getCompilerOptions(); - let newSettings = hostCache.compilationSettings(); - let changesInCompilationSettingsAffectSyntax = oldSettings && + const oldSettings = program && program.getCompilerOptions(); + const newSettings = hostCache.compilationSettings(); + const changesInCompilationSettingsAffectSyntax = oldSettings && (oldSettings.target !== newSettings.target || oldSettings.module !== newSettings.module || oldSettings.noResolve !== newSettings.noResolve || - oldSettings.jsx !== newSettings.jsx || + oldSettings.jsx !== newSettings.jsx || oldSettings.allowJs !== newSettings.allowJs); // Now create a new compiler - let compilerHost: CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: getOrCreateSourceFile, getCancellationToken: () => cancellationToken, getCanonicalFileName, @@ -2766,22 +2765,22 @@ namespace ts { }, readFile: (fileName): string => { // stub missing host functionality - let entry = hostCache.getOrCreateEntry(fileName); + const entry = hostCache.getOrCreateEntry(fileName); return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); } }; if (host.resolveModuleNames) { - compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile) + compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile); } - let newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); + const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); // Release any files we have acquired in the old program but are // not part of the new program. if (program) { - let oldSourceFiles = program.getSourceFiles(); - for (let oldSourceFile of oldSourceFiles) { + const oldSourceFiles = program.getSourceFiles(); + for (const oldSourceFile of oldSourceFiles) { if (!newProgram.getSourceFile(oldSourceFile.fileName) || changesInCompilationSettingsAffectSyntax) { documentRegistry.releaseDocument(oldSourceFile.fileName, oldSettings); } @@ -2804,7 +2803,7 @@ namespace ts { // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined // to the program to allow reporting of errors for missing files. - let hostFileInformation = hostCache.getOrCreateEntry(fileName); + const hostFileInformation = hostCache.getOrCreateEntry(fileName); if (!hostFileInformation) { return undefined; } @@ -2814,7 +2813,7 @@ namespace ts { // can not be reused. we have to dump all syntax trees and create new ones. if (!changesInCompilationSettingsAffectSyntax) { // Check if the old program had this file already - let oldSourceFile = program && program.getSourceFile(fileName); + const oldSourceFile = program && program.getSourceFile(fileName); if (oldSourceFile) { // We already had a source file for this file name. Go to the registry to // ensure that we get the right up to date version of it. We need this to @@ -2851,7 +2850,7 @@ namespace ts { if (!sourceFile) { return false; } - let path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); + const path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); return sourceFile.version === hostCache.getVersion(path); } @@ -2862,13 +2861,13 @@ namespace ts { } // If number of files in the program do not match, it is not up-to-date - let rootFileNames = hostCache.getRootFileNames(); + const rootFileNames = hostCache.getRootFileNames(); if (program.getSourceFiles().length !== rootFileNames.length) { return false; } // If any file is not up-to-date, then the whole program is not up-to-date - for (let fileName of rootFileNames) { + for (const fileName of rootFileNames) { if (!sourceFileUpToDate(program.getSourceFile(fileName))) { return false; } @@ -2910,18 +2909,18 @@ namespace ts { function getSemanticDiagnostics(fileName: string): Diagnostic[] { synchronizeHostData(); - let targetSourceFile = getValidSourceFile(fileName); + const targetSourceFile = getValidSourceFile(fileName); // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. // Therefore only get diagnostics for given file. - let semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); + const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); if (!program.getCompilerOptions().declaration) { return semanticDiagnostics; } // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface - let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); + const declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return concatenate(semanticDiagnostics, declarationDiagnostics); } @@ -2937,14 +2936,14 @@ namespace ts { * @return undefined if the name is of external module otherwise a name with striped of any quote */ function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean, location: Node): string { - let displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); + const displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); if (displayName) { - let firstCharCode = displayName.charCodeAt(0); + const firstCharCode = displayName.charCodeAt(0); // First check of the displayName is not external module; if it is an external module, it is not valid entry if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) { // If the symbol is external module, don't show it in the completion list - // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there) + // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) return undefined; } } @@ -2987,20 +2986,20 @@ namespace ts { } function getCompletionData(fileName: string, position: number) { - let typeChecker = program.getTypeChecker(); - let syntacticStart = new Date().getTime(); - let sourceFile = getValidSourceFile(fileName); - let isJavaScriptFile = isSourceFileJavaScript(sourceFile); + const typeChecker = program.getTypeChecker(); + const syntacticStart = new Date().getTime(); + const sourceFile = getValidSourceFile(fileName); + const isJavaScriptFile = isSourceFileJavaScript(sourceFile); let isJsDocTagName = false; let start = new Date().getTime(); - let currentToken = getTokenAtPosition(sourceFile, position); + const currentToken = getTokenAtPosition(sourceFile, position); log("getCompletionData: Get current token: " + (new Date().getTime() - start)); start = new Date().getTime(); // Completion not allowed inside comments, bail out if this is the case - let insideComment = isInsideComment(sourceFile, currentToken, position); + const insideComment = isInsideComment(sourceFile, currentToken, position); log("getCompletionData: Is inside comment: " + (new Date().getTime() - start)); if (insideComment) { @@ -3014,7 +3013,7 @@ namespace ts { // /** @type {number | string} */ // Completion should work in the brackets let insideJsDocTagExpression = false; - let tag = getJsDocTagAtPosition(sourceFile, position); + const tag = getJsDocTagAtPosition(sourceFile, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { isJsDocTagName = true; @@ -3024,7 +3023,7 @@ namespace ts { case SyntaxKind.JSDocTypeTag: case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocReturnTag: - let tagWithExpression = tag; + const tagWithExpression = tag; if (tagWithExpression.typeExpression) { insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; } @@ -3045,7 +3044,7 @@ namespace ts { } start = new Date().getTime(); - let previousToken = findPrecedingToken(position, sourceFile); + const previousToken = findPrecedingToken(position, sourceFile); log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start)); // The decision to provide completion depends on the contextToken, which is determined through the previousToken. @@ -3055,7 +3054,7 @@ namespace ts { // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) { - let start = new Date().getTime(); + const start = new Date().getTime(); contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile); log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start)); } @@ -3076,7 +3075,7 @@ namespace ts { return undefined; } - let { parent, kind } = contextToken; + const { parent, kind } = contextToken; if (kind === SyntaxKind.DotToken) { if (parent.kind === SyntaxKind.PropertyAccessExpression) { node = (contextToken.parent).expression; @@ -3103,7 +3102,7 @@ namespace ts { } } - let semanticStart = new Date().getTime(); + const semanticStart = new Date().getTime(); let isMemberCompletion: boolean; let isNewIdentifierLocation: boolean; let symbols: Symbol[] = []; @@ -3112,7 +3111,7 @@ namespace ts { getTypeScriptMemberSymbols(); } else if (isRightOfOpenTag) { - let tagSymbols = typeChecker.getJsxIntrinsicTagNames(); + const tagSymbols = typeChecker.getJsxIntrinsicTagNames(); if (tryGetGlobalSymbols()) { symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & SymbolFlags.Value))); } @@ -3123,7 +3122,7 @@ namespace ts { isNewIdentifierLocation = false; } else if (isStartingCloseTag) { - let tagName = (contextToken.parent.parent).openingElement.tagName; + const tagName = (contextToken.parent.parent).openingElement.tagName; symbols = [typeChecker.getSymbolAtLocation(tagName)]; isMemberCompletion = true; @@ -3157,7 +3156,7 @@ namespace ts { if (symbol && symbol.flags & SymbolFlags.HasExports) { // Extract module or enum members - let exportedSymbols = typeChecker.getExportsOfModule(symbol); + const exportedSymbols = typeChecker.getExportsOfModule(symbol); forEach(exportedSymbols, symbol => { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); @@ -3166,14 +3165,14 @@ namespace ts { } } - let type = typeChecker.getTypeAtLocation(node); + const type = typeChecker.getTypeAtLocation(node); addTypeProperties(type); } function addTypeProperties(type: Type) { if (type) { // Filter private properties - for (let symbol of type.getApparentProperties()) { + for (const symbol of type.getApparentProperties()) { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); } @@ -3185,8 +3184,8 @@ namespace ts { // each individual type has. This is because we're going to add all identifiers // anyways. So we might as well elevate the members that were at least part // of the individual types to a higher status since we know what they are. - let unionType = type; - for (let elementType of unionType.types) { + const unionType = type; + for (const elementType of unionType.types) { addTypeProperties(elementType); } } @@ -3256,14 +3255,14 @@ namespace ts { // - 'contextToken' was adjusted to the token prior to 'previousToken' // because we were at the end of an identifier. // - 'previousToken' is defined. - let adjustedPosition = previousToken !== contextToken ? + const adjustedPosition = previousToken !== contextToken ? previousToken.getStart() : position; - let scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; + const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; /// TODO filter meaning based on the current context - let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; + const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); return true; @@ -3282,8 +3281,8 @@ namespace ts { } function isCompletionListBlocker(contextToken: Node): boolean { - let start = new Date().getTime(); - let result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || + const start = new Date().getTime(); + const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken) || isInJsxText(contextToken); @@ -3310,27 +3309,27 @@ namespace ts { function isNewIdentifierDefinitionLocation(previousToken: Node): boolean { if (previousToken) { - let containingNodeKind = previousToken.parent.kind; + const containingNodeKind = previousToken.parent.kind; switch (previousToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.CallExpression // func( a, | || containingNodeKind === SyntaxKind.Constructor // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ || containingNodeKind === SyntaxKind.NewExpression // new C(a, | || containingNodeKind === SyntaxKind.ArrayLiteralExpression // [a, | - || containingNodeKind === SyntaxKind.BinaryExpression // let x = (a, | + || containingNodeKind === SyntaxKind.BinaryExpression // const x = (a, | || containingNodeKind === SyntaxKind.FunctionType; // var x: (s: string, list| case SyntaxKind.OpenParenToken: return containingNodeKind === SyntaxKind.CallExpression // func( | || containingNodeKind === SyntaxKind.Constructor // constructor( | || containingNodeKind === SyntaxKind.NewExpression // new C(a| - || containingNodeKind === SyntaxKind.ParenthesizedExpression // let x = (a| + || containingNodeKind === SyntaxKind.ParenthesizedExpression // const x = (a| || containingNodeKind === SyntaxKind.ParenthesizedType; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ case SyntaxKind.OpenBracketToken: return containingNodeKind === SyntaxKind.ArrayLiteralExpression // [ | || containingNodeKind === SyntaxKind.IndexSignature // [ | : string ] - || containingNodeKind === SyntaxKind.ComputedPropertyName // [ | /* this can become an index signature */ + || containingNodeKind === SyntaxKind.ComputedPropertyName; // [ | /* this can become an index signature */ case SyntaxKind.ModuleKeyword: // module | case SyntaxKind.NamespaceKeyword: // namespace | @@ -3343,7 +3342,7 @@ namespace ts { return containingNodeKind === SyntaxKind.ClassDeclaration; // class A{ | case SyntaxKind.EqualsToken: - return containingNodeKind === SyntaxKind.VariableDeclaration // let x = a| + return containingNodeKind === SyntaxKind.VariableDeclaration // const x = a| || containingNodeKind === SyntaxKind.BinaryExpression; // x = a| case SyntaxKind.TemplateHead: @@ -3375,8 +3374,8 @@ namespace ts { || contextToken.kind === SyntaxKind.StringLiteralType || contextToken.kind === SyntaxKind.RegularExpressionLiteral || isTemplateLiteralKind(contextToken.kind)) { - let start = contextToken.getStart(); - let end = contextToken.getEnd(); + const start = contextToken.getStart(); + const end = contextToken.getEnd(); // To be "in" one of these literals, the position has to be: // 1. entirely within the token text. @@ -3420,7 +3419,7 @@ namespace ts { // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; - let rootDeclaration = getRootDeclaration(objectLikeContainer.parent); + const rootDeclaration = getRootDeclaration(objectLikeContainer.parent); if (isVariableLike(rootDeclaration)) { // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired @@ -3431,7 +3430,7 @@ namespace ts { } } else { - Debug.fail("Root declaration is not variable-like.") + Debug.fail("Root declaration is not variable-like."); } } else { @@ -3442,7 +3441,7 @@ namespace ts { return false; } - let typeMembers = typeChecker.getPropertiesOfType(typeForObject); + const typeMembers = typeChecker.getPropertiesOfType(typeForObject); if (typeMembers && typeMembers.length > 0) { // Add filtered items to the completion list symbols = filterObjectMembersList(typeMembers, existingMembers); @@ -3466,11 +3465,11 @@ namespace ts { * @returns true if 'symbols' was successfully populated; false otherwise. */ function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports: NamedImportsOrExports): boolean { - let declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? + const declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? SyntaxKind.ImportDeclaration : SyntaxKind.ExportDeclaration; - let importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); - let moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + const importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); + const moduleSpecifier = importOrExportDeclaration.moduleSpecifier; if (!moduleSpecifier) { return false; @@ -3480,7 +3479,7 @@ namespace ts { isNewIdentifierLocation = false; let exports: Symbol[]; - let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); if (moduleSpecifierSymbol) { exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } @@ -3497,9 +3496,9 @@ namespace ts { function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | BindingPattern { if (contextToken) { switch (contextToken.kind) { - case SyntaxKind.OpenBraceToken: // let x = { | - case SyntaxKind.CommaToken: // let x = { a: 0, | - let parent = contextToken.parent; + case SyntaxKind.OpenBraceToken: // const x = { | + case SyntaxKind.CommaToken: // const x = { a: 0, | + const parent = contextToken.parent; if (parent && (parent.kind === SyntaxKind.ObjectLiteralExpression || parent.kind === SyntaxKind.ObjectBindingPattern)) { return parent; } @@ -3532,8 +3531,8 @@ namespace ts { function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement { if (contextToken) { - let parent = contextToken.parent; - switch(contextToken.kind) { + const parent = contextToken.parent; + switch (contextToken.kind) { case SyntaxKind.LessThanSlashToken: case SyntaxKind.SlashToken: case SyntaxKind.Identifier: @@ -3596,7 +3595,7 @@ namespace ts { * @returns true if we are certain that the currently edited location must define a new location; false otherwise. */ function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean { - let containingNodeKind = contextToken.parent.kind; + const containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.VariableDeclaration || @@ -3626,13 +3625,13 @@ namespace ts { case SyntaxKind.OpenBraceToken: return containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { | containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface a { | - containingNodeKind === SyntaxKind.TypeLiteral; // let x : { | + containingNodeKind === SyntaxKind.TypeLiteral; // const x : { | case SyntaxKind.SemicolonToken: return containingNodeKind === SyntaxKind.PropertySignature && contextToken.parent && contextToken.parent.parent && (contextToken.parent.parent.kind === SyntaxKind.InterfaceDeclaration || // interface a { f; | - contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // let x : { a; | + contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // const x : { a; | case SyntaxKind.LessThanToken: return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< | @@ -3699,7 +3698,7 @@ namespace ts { function isDotOfNumericLiteral(contextToken: Node): boolean { if (contextToken.kind === SyntaxKind.NumericLiteral) { - let text = contextToken.getFullText(); + const text = contextToken.getFullText(); return text.charAt(text.length - 1) === "."; } @@ -3716,15 +3715,15 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - let exisingImportsOrExports: Map = {}; + const exisingImportsOrExports: Map = {}; - for (let element of namedImportsOrExports) { + for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out if (element.getStart() <= position && position <= element.getEnd()) { continue; } - let name = element.propertyName || element.name; + const name = element.propertyName || element.name; exisingImportsOrExports[name.text] = true; } @@ -3746,8 +3745,8 @@ namespace ts { return contextualMemberSymbols; } - let existingMemberNames: Map = {}; - for (let m of existingMembers) { + const existingMemberNames: Map = {}; + for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && m.kind !== SyntaxKind.ShorthandPropertyAssignment && @@ -3766,7 +3765,7 @@ namespace ts { if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list if ((m).propertyName.kind === SyntaxKind.Identifier) { - existingName = ((m).propertyName).text + existingName = ((m).propertyName).text; } } else { @@ -3789,8 +3788,8 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - let seenNames: Map = {}; - for (let attr of attributes) { + const seenNames: Map = {}; + for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (attr.getStart() <= position && position <= attr.getEnd()) { continue; @@ -3809,21 +3808,21 @@ namespace ts { function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo { synchronizeHostData(); - let completionData = getCompletionData(fileName, position); + const completionData = getCompletionData(fileName, position); if (!completionData) { return undefined; } - let { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; + const { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; if (isJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; } - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let entries: CompletionEntry[] = []; + const entries: CompletionEntry[] = []; if (isRightOfDot && isSourceFileJavaScript(sourceFile)) { const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries); @@ -3845,16 +3844,16 @@ namespace ts { return { isMemberCompletion, isNewIdentifierLocation, entries }; function getJavaScriptCompletionEntries(sourceFile: SourceFile, uniqueNames: Map): CompletionEntry[] { - let entries: CompletionEntry[] = []; - let target = program.getCompilerOptions().target; + const entries: CompletionEntry[] = []; + const target = program.getCompilerOptions().target; - let nameTable = getNameTable(sourceFile); - for (let name in nameTable) { + const nameTable = getNameTable(sourceFile); + for (const name in nameTable) { if (!uniqueNames[name]) { uniqueNames[name] = name; - let displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks:*/ true); + const displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks*/ true); if (displayName) { - let entry = { + const entry = { name: displayName, kind: ScriptElementKind.warning, kindModifiers: "", @@ -3875,7 +3874,7 @@ namespace ts { kind: ScriptElementKind.keyword, kindModifiers: "", sortText: "0", - } + }; })); } @@ -3883,7 +3882,7 @@ namespace ts { // Try to get a valid display name for this symbol, if we could not find one, then ignore it. // We would like to only show things that can be added after a dot, so for instance numeric properties can // not be accessed with a dot (a.1 <- invalid) - let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true, location); + const displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks*/ true, location); if (!displayName) { return undefined; } @@ -3905,13 +3904,13 @@ namespace ts { } function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[]): Map { - let start = new Date().getTime(); - let uniqueNames: Map = {}; + const start = new Date().getTime(); + const uniqueNames: Map = {}; if (symbols) { - for (let symbol of symbols) { - let entry = createCompletionEntry(symbol, location); + for (const symbol of symbols) { + const entry = createCompletionEntry(symbol, location); if (entry) { - let id = escapeIdentifier(entry.name); + const id = escapeIdentifier(entry.name); if (!lookUp(uniqueNames, id)) { entries.push(entry); uniqueNames[id] = id; @@ -3929,19 +3928,19 @@ namespace ts { synchronizeHostData(); // Compute all the completion symbols again. - let completionData = getCompletionData(fileName, position); + const completionData = getCompletionData(fileName, position); if (completionData) { - let { symbols, location } = completionData; + const { symbols, location } = completionData; // Find the symbol with the matching entry name. - let target = program.getCompilerOptions().target; + const target = program.getCompilerOptions().target; // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false, location) === entryName ? s : undefined); + const symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks*/ false, location) === entryName ? s : undefined); if (symbol) { - let { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); + const { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); return { name: entryName, kindModifiers: getSymbolModifiers(symbol), @@ -3953,7 +3952,7 @@ namespace ts { } // Didn't find a symbol with this name. See if we can find a keyword instead. - let keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); + const keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); if (keywordCompletion) { return { name: entryName, @@ -3969,7 +3968,7 @@ namespace ts { // TODO(drosen): use contextual SemanticMeaning. function getSymbolKind(symbol: Symbol, location: Node): string { - let flags = symbol.getFlags(); + const flags = symbol.getFlags(); if (flags & SymbolFlags.Class) return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? ScriptElementKind.localClassElement : ScriptElementKind.classElement; @@ -3978,7 +3977,7 @@ namespace ts { if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement; if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; - let result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); + const result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); if (result === ScriptElementKind.unknown) { if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement; @@ -3990,7 +3989,7 @@ namespace ts { } function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, location: Node) { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); if (typeChecker.isUndefinedSymbol(symbol)) { return ScriptElementKind.variableElement; @@ -4019,8 +4018,8 @@ namespace ts { if (flags & SymbolFlags.Property) { if (flags & SymbolFlags.SyntheticProperty) { // If union property is result of union of non method (property/accessors/variables), it is labeled as property - let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { - let rootSymbolFlags = rootSymbol.getFlags(); + const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { + const rootSymbolFlags = rootSymbol.getFlags(); if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) { return ScriptElementKind.memberVariableElement; } @@ -4028,8 +4027,8 @@ namespace ts { }); if (!unionPropertyKind) { // If this was union of all methods, - //make sure it has call signatures before we can label it as method - let typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + // make sure it has call signatures before we can label it as method + const typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { return ScriptElementKind.memberFunctionElement; } @@ -4053,11 +4052,11 @@ namespace ts { function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, location: Node, semanticMeaning = getMeaningFromLocation(location)) { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); - let displayParts: SymbolDisplayPart[] = []; + const displayParts: SymbolDisplayPart[] = []; let documentation: SymbolDisplayPart[]; - let symbolFlags = symbol.flags; + const symbolFlags = symbol.flags; let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; let type: Type; @@ -4073,7 +4072,7 @@ namespace ts { type = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { - let right = (location.parent).name; + const right = (location.parent).name; // Either the location is on the right of a property access, or on the left and the right is missing if (right === location || (right && right.getFullWidth() === 0)) { location = location.parent; @@ -4090,15 +4089,15 @@ namespace ts { } if (callExpression) { - let candidateSignatures: Signature[] = []; + const candidateSignatures: Signature[] = []; signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); if (!signature && candidateSignatures.length) { // Use the first candidate: signature = candidateSignatures[0]; } - let useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; - let allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + const useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; + const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { // Get the first signature if there is one -- allSignatures may contain @@ -4156,8 +4155,8 @@ namespace ts { else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & SymbolFlags.Accessor)) || // name of function declaration (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it - let functionDeclaration = location.parent; - let allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); + const functionDeclaration = location.parent; + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); } @@ -4226,8 +4225,8 @@ namespace ts { } if (symbolFlags & SymbolFlags.Module) { addNewLineIfDisplayPartsExist(); - let declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); - let isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; + const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); + const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword)); displayParts.push(spacePart()); addFullSymbolName(symbol); @@ -4279,9 +4278,9 @@ namespace ts { } if (symbolFlags & SymbolFlags.EnumMember) { addPrefixForAnyFunctionOrVar(symbol, "enum member"); - let declaration = symbol.declarations[0]; + const declaration = symbol.declarations[0]; if (declaration.kind === SyntaxKind.EnumMember) { - let constantValue = typeChecker.getConstantValue(declaration); + const constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4297,7 +4296,7 @@ namespace ts { addFullSymbolName(symbol); ts.forEach(symbol.declarations, declaration => { if (declaration.kind === SyntaxKind.ImportEqualsDeclaration) { - let importEqualsDeclaration = declaration; + const importEqualsDeclaration = declaration; if (isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4308,7 +4307,7 @@ namespace ts { displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } else { - let internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); + const internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4332,7 +4331,7 @@ namespace ts { displayParts.push(spacePart()); // If the type is type parameter, format it specially if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) { - let typeParameterParts = mapToDisplayParts(writer => { + const typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4347,7 +4346,7 @@ namespace ts { symbolFlags & SymbolFlags.Signature || symbolFlags & SymbolFlags.Accessor || symbolKind === ScriptElementKind.memberFunctionElement) { - let allSignatures = type.getCallSignatures(); + const allSignatures = type.getCallSignatures(); addSignatureDisplayParts(allSignatures[0], allSignatures); } } @@ -4370,7 +4369,7 @@ namespace ts { } function addFullSymbolName(symbol: Symbol, enclosingDeclaration?: Node) { - let fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, + const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing); addRange(displayParts, fullSymbolDisplayParts); } @@ -4416,7 +4415,7 @@ namespace ts { } function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) { - let typeParameterParts = mapToDisplayParts(writer => { + const typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4426,8 +4425,8 @@ namespace ts { function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const sourceFile = getValidSourceFile(fileName); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } @@ -4436,8 +4435,8 @@ namespace ts { return undefined; } - let typeChecker = program.getTypeChecker(); - let symbol = typeChecker.getSymbolAtLocation(node); + const typeChecker = program.getTypeChecker(); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { // Try getting just type at this position and show @@ -4449,7 +4448,7 @@ namespace ts { case SyntaxKind.ThisType: case SyntaxKind.SuperKeyword: // For the identifiers/this/super etc get the type at position - let type = typeChecker.getTypeAtLocation(node); + const type = typeChecker.getTypeAtLocation(node); if (type) { return { kind: ScriptElementKind.unknown, @@ -4464,7 +4463,7 @@ namespace ts { return undefined; } - let displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); + const displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); return { kind: displayPartsDocumentationsAndKind.symbolKind, kindModifiers: getSymbolModifiers(symbol), @@ -4486,13 +4485,13 @@ namespace ts { } function getDefinitionFromSymbol(symbol: Symbol, node: Node): DefinitionInfo[] { - let typeChecker = program.getTypeChecker(); - let result: DefinitionInfo[] = []; - let declarations = symbol.getDeclarations(); - let symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol - let symbolKind = getSymbolKind(symbol, node); - let containerSymbol = symbol.parent; - let containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; + const typeChecker = program.getTypeChecker(); + const result: DefinitionInfo[] = []; + const declarations = symbol.getDeclarations(); + const symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol + const symbolKind = getSymbolKind(symbol, node); + const containerSymbol = symbol.parent; + const containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { @@ -4510,7 +4509,7 @@ namespace ts { if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) { if (symbol.flags & SymbolFlags.Class) { // Find the first class-like declaration and try to get the construct signature. - for (let declaration of symbol.getDeclarations()) { + for (const declaration of symbol.getDeclarations()) { if (isClassLike(declaration)) { return tryAddSignature(declaration.members, /*selectConstructors*/ true, @@ -4535,7 +4534,7 @@ namespace ts { } function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { - let declarations: Declaration[] = []; + const declarations: Declaration[] = []; let definition: Declaration; forEach(signatureDeclarations, d => { @@ -4563,24 +4562,24 @@ namespace ts { function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } // Labels if (isJumpStatementTarget(node)) { - let labelName = (node).text; - let label = getTargetLabel((node.parent), (node).text); + const labelName = (node).text; + const label = getTargetLabel((node.parent), (node).text); return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } /// Triple slash reference comments - let comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); + const comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); if (comment) { - let referenceFile = tryResolveScriptReference(program, sourceFile, comment); + const referenceFile = tryResolveScriptReference(program, sourceFile, comment); if (referenceFile) { return [{ fileName: referenceFile.fileName, @@ -4594,7 +4593,7 @@ namespace ts { return undefined; } - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); let symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. node is string or number keyword, @@ -4608,7 +4607,7 @@ namespace ts { // import {A, B} from "mod"; // to jump to the implementation directly. if (symbol.flags & SymbolFlags.Alias) { - let declaration = symbol.declarations[0]; + const declaration = symbol.declarations[0]; if (node.kind === SyntaxKind.Identifier && node.parent === declaration) { symbol = typeChecker.getAliasedSymbol(symbol); } @@ -4620,15 +4619,15 @@ namespace ts { // is performed at the location of property access, we would like to go to definition of the property in the short-hand // assignment. This case and others are handled by the following code. if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - let shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); if (!shorthandSymbol) { return []; } - let shorthandDeclarations = shorthandSymbol.getDeclarations(); - let shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); - let shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); - let shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); + const shorthandDeclarations = shorthandSymbol.getDeclarations(); + const shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); + const shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); + const shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); return map(shorthandDeclarations, declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); } @@ -4640,27 +4639,27 @@ namespace ts { function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { return undefined; } - let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); + const type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); if (!type) { return undefined; } if (type.flags & TypeFlags.Union) { - let result: DefinitionInfo[] = []; + const result: DefinitionInfo[] = []; forEach((type).types, t => { if (t.symbol) { addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(t.symbol, node)); @@ -4680,7 +4679,7 @@ namespace ts { let results = getOccurrencesAtPositionCore(fileName, position); if (results) { - let sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); + const sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); // Get occurrences only supports reporting occurrences for the file queried. So // filter down to that list. @@ -4694,10 +4693,10 @@ namespace ts { synchronizeHostData(); filesToSearch = map(filesToSearch, normalizeSlashes); - let sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); - let sourceFile = getValidSourceFile(fileName); + const sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node) { return undefined; } @@ -4705,8 +4704,8 @@ namespace ts { return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); function getHighlightSpanForNode(node: Node): HighlightSpan { - let start = node.getStart(); - let end = node.getEnd(); + const start = node.getStart(); + const end = node.getEnd(); return { fileName: sourceFile.fileName, @@ -4723,7 +4722,7 @@ namespace ts { isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) { - let referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings:*/ false, /*findInComments:*/ false); + const referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false); return convertReferencedSymbols(referencedSymbols); } @@ -4734,11 +4733,11 @@ namespace ts { return undefined; } - let fileNameToDocumentHighlights: Map = {}; - let result: DocumentHighlights[] = []; - for (let referencedSymbol of referencedSymbols) { - for (let referenceEntry of referencedSymbol.references) { - let fileName = referenceEntry.fileName; + const fileNameToDocumentHighlights: Map = {}; + const result: DocumentHighlights[] = []; + for (const referencedSymbol of referencedSymbols) { + for (const referenceEntry of referencedSymbol.references) { + const fileName = referenceEntry.fileName; let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName); if (!documentHighlights) { documentHighlights = { fileName, highlightSpans: [] }; @@ -4759,9 +4758,9 @@ namespace ts { } function getSyntacticDocumentHighlights(node: Node): DocumentHighlights[] { - let fileName = sourceFile.fileName; + const fileName = sourceFile.fileName; - let highlightSpans = getHighlightSpans(node); + const highlightSpans = getHighlightSpans(node); if (!highlightSpans || highlightSpans.length === 0) { return undefined; } @@ -4865,7 +4864,7 @@ namespace ts { * into function boundaries and try-blocks with catch-clauses. */ function aggregateOwnedThrowStatements(node: Node): ThrowStatement[] { - let statementAccumulator: ThrowStatement[] = [] + const statementAccumulator: ThrowStatement[] = []; aggregate(node); return statementAccumulator; @@ -4874,7 +4873,7 @@ namespace ts { statementAccumulator.push(node); } else if (node.kind === SyntaxKind.TryStatement) { - let tryStatement = node; + const tryStatement = node; if (tryStatement.catchClause) { aggregate(tryStatement.catchClause); @@ -4905,7 +4904,7 @@ namespace ts { let child: Node = throwStatement; while (child.parent) { - let parent = child.parent; + const parent = child.parent; if (isFunctionBlock(parent) || parent.kind === SyntaxKind.SourceFile) { return parent; @@ -4914,7 +4913,7 @@ namespace ts { // A throw-statement is only owned by a try-statement if the try-statement has // a catch clause, and if the throw-statement occurs within the try block. if (parent.kind === SyntaxKind.TryStatement) { - let tryStatement = parent; + const tryStatement = parent; if (tryStatement.tryBlock === child && tryStatement.catchClause) { return child; @@ -4928,7 +4927,7 @@ namespace ts { } function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] { - let statementAccumulator: BreakOrContinueStatement[] = [] + const statementAccumulator: BreakOrContinueStatement[] = []; aggregate(node); return statementAccumulator; @@ -4944,7 +4943,7 @@ namespace ts { } function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean { - let actualOwner = getBreakOrContinueOwner(statement); + const actualOwner = getBreakOrContinueOwner(statement); return actualOwner && actualOwner === owner; } @@ -4979,7 +4978,7 @@ namespace ts { } function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): HighlightSpan[] { - let container = declaration.parent; + const container = declaration.parent; // Make sure we only highlight the keyword when it makes sense to do so. if (isAccessibilityModifier(modifier)) { @@ -5009,8 +5008,8 @@ namespace ts { return undefined; } - let keywords: Node[] = []; - let modifierFlag: NodeFlags = getFlagFromModifier(modifier); + const keywords: Node[] = []; + const modifierFlag: NodeFlags = getFlagFromModifier(modifier); let nodes: Node[]; switch (container.kind) { @@ -5035,7 +5034,7 @@ namespace ts { // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. if (modifierFlag & NodeFlags.AccessibilityModifier) { - let constructor = forEach((container).members, member => { + const constructor = forEach((container).members, member => { return member.kind === SyntaxKind.Constructor && member; }); @@ -5048,7 +5047,7 @@ namespace ts { } break; default: - Debug.fail("Invalid container kind.") + Debug.fail("Invalid container kind."); } forEach(nodes, node => { @@ -5091,7 +5090,7 @@ namespace ts { } function getGetAndSetOccurrences(accessorDeclaration: AccessorDeclaration): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.GetAccessor); tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.SetAccessor); @@ -5099,7 +5098,7 @@ namespace ts { return map(keywords, getHighlightSpanForNode); function tryPushAccessorKeyword(accessorSymbol: Symbol, accessorKind: SyntaxKind): void { - let accessor = getDeclarationOfKind(accessorSymbol, accessorKind); + const accessor = getDeclarationOfKind(accessorSymbol, accessorKind); if (accessor) { forEach(accessor.getChildren(), child => pushKeywordIf(keywords, child, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword)); @@ -5108,9 +5107,9 @@ namespace ts { } function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): HighlightSpan[] { - let declarations = constructorDeclaration.symbol.getDeclarations() + const declarations = constructorDeclaration.symbol.getDeclarations(); - let keywords: Node[] = []; + const keywords: Node[] = []; forEach(declarations, declaration => { forEach(declaration.getChildren(), token => { @@ -5122,12 +5121,12 @@ namespace ts { } function getLoopBreakContinueOccurrences(loopNode: IterationStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. if (loopNode.kind === SyntaxKind.DoStatement) { - let loopTokens = loopNode.getChildren(); + const loopTokens = loopNode.getChildren(); for (let i = loopTokens.length - 1; i >= 0; i--) { if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) { @@ -5137,7 +5136,7 @@ namespace ts { } } - let breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); + const breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(loopNode, statement)) { @@ -5149,7 +5148,7 @@ namespace ts { } function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { - let owner = getBreakOrContinueOwner(breakOrContinueStatement); + const owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { @@ -5158,7 +5157,7 @@ namespace ts { case SyntaxKind.ForOfStatement: case SyntaxKind.DoStatement: case SyntaxKind.WhileStatement: - return getLoopBreakContinueOccurrences(owner) + return getLoopBreakContinueOccurrences(owner); case SyntaxKind.SwitchStatement: return getSwitchCaseDefaultOccurrences(owner); @@ -5169,7 +5168,7 @@ namespace ts { } function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword); @@ -5177,7 +5176,7 @@ namespace ts { forEach(switchStatement.caseBlock.clauses, clause => { pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword); - let breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); + const breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(switchStatement, statement)) { @@ -5190,7 +5189,7 @@ namespace ts { } function getTryCatchFinallyOccurrences(tryStatement: TryStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); @@ -5199,7 +5198,7 @@ namespace ts { } if (tryStatement.finallyBlock) { - let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); + const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword); } @@ -5207,13 +5206,13 @@ namespace ts { } function getThrowOccurrences(throwStatement: ThrowStatement): HighlightSpan[] { - let owner = getThrowStatementOwner(throwStatement); + const owner = getThrowStatementOwner(throwStatement); if (!owner) { return undefined; } - let keywords: Node[] = []; + const keywords: Node[] = []; forEach(aggregateOwnedThrowStatements(owner), throwStatement => { pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword); @@ -5231,14 +5230,14 @@ namespace ts { } function getReturnOccurrences(returnStatement: ReturnStatement): HighlightSpan[] { - let func = getContainingFunction(returnStatement); + const func = getContainingFunction(returnStatement); // If we didn't find a containing function with a block body, bail out. if (!(func && hasKind(func.body, SyntaxKind.Block))) { return undefined; } - let keywords: Node[] = [] + const keywords: Node[] = []; forEachReturnStatement(func.body, returnStatement => { pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword); }); @@ -5252,7 +5251,7 @@ namespace ts { } function getIfElseOccurrences(ifStatement: IfStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; // Traverse upwards through all parent if-statements linked by their else-branches. while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (ifStatement.parent).elseStatement === ifStatement) { @@ -5261,7 +5260,7 @@ namespace ts { // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. while (ifStatement) { - let children = ifStatement.getChildren(); + const children = ifStatement.getChildren(); pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword); // Generally the 'else' keyword is second-to-last, so we traverse backwards. @@ -5272,20 +5271,20 @@ namespace ts { } if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) { - break + break; } ifStatement = ifStatement.elseStatement; } - let result: HighlightSpan[] = []; + const result: HighlightSpan[] = []; // We'd like to highlight else/ifs together if they are only separated by whitespace // (i.e. the keywords are separated by no comments, no newlines). for (let i = 0; i < keywords.length; i++) { if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) { - let elseKeyword = keywords[i]; - let ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. + const elseKeyword = keywords[i]; + const ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. let shouldCombindElseAndIf = true; @@ -5328,9 +5327,9 @@ namespace ts { return undefined; } - let result: ReferenceEntry[] = []; - for (let entry of documentHighlights) { - for (let highlightSpan of entry.highlightSpans) { + const result: ReferenceEntry[] = []; + for (const entry of documentHighlights) { + for (const highlightSpan of entry.highlightSpans) { result.push({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, @@ -5348,9 +5347,9 @@ namespace ts { return undefined; } - let referenceEntries: ReferenceEntry[] = []; + const referenceEntries: ReferenceEntry[] = []; - for (let referenceSymbol of referenceSymbols) { + for (const referenceSymbol of referenceSymbols) { addRange(referenceEntries, referenceSymbol.references); } @@ -5358,17 +5357,17 @@ namespace ts { } function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] { - let referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); + const referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); return convertReferences(referencedSymbols); } function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] { - let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); return convertReferences(referencedSymbols); } - function findReferences(fileName: string, position: number): ReferencedSymbol[]{ - let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + function findReferences(fileName: string, position: number): ReferencedSymbol[] { + const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); // Only include referenced symbols that have a valid definition. return filter(referencedSymbols, rs => !!rs.definition); @@ -5377,17 +5376,17 @@ namespace ts { function findReferencedSymbols(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } if (node.kind !== SyntaxKind.Identifier && // TODO (drosen): This should be enabled in a later release - currently breaks rename. - //node.kind !== SyntaxKind.ThisKeyword && - //node.kind !== SyntaxKind.SuperKeyword && + // node.kind !== SyntaxKind.ThisKeyword && + // node.kind !== SyntaxKind.SuperKeyword && !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && !isNameOfExternalModuleImportOrDeclaration(node)) { return undefined; @@ -5398,12 +5397,12 @@ namespace ts { } function getReferencedSymbolsForNode(node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); // Labels if (isLabelName(node)) { if (isJumpStatementTarget(node)) { - let labelDefinition = getTargetLabel((node.parent), (node).text); + const labelDefinition = getTargetLabel((node.parent), (node).text); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; @@ -5422,7 +5421,7 @@ namespace ts { return getReferencesForSuperKeyword(node); } - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. unknown identifier if (!symbol) { @@ -5430,7 +5429,7 @@ namespace ts { return undefined; } - let declarations = symbol.declarations; + const declarations = symbol.declarations; // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol if (!declarations || !declarations.length) { @@ -5440,29 +5439,29 @@ namespace ts { let result: ReferencedSymbol[]; // Compute the meaning from the location and the symbol it references - let searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); + const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); // Get the text to search for. // Note: if this is an external module symbol, the name doesn't include quotes. - let declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). - let scope = getSymbolScope(symbol); + const scope = getSymbolScope(symbol); // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. - let symbolToIndex: number[] = []; + const symbolToIndex: number[] = []; if (scope) { result = []; getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { - let internedName = getInternedName(symbol, node, declarations) - for (let sourceFile of sourceFiles) { + const internedName = getInternedName(symbol, node, declarations); + for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); - let nameTable = getNameTable(sourceFile); + const nameTable = getNameTable(sourceFile); if (lookUp(nameTable, internedName)) { result = result || []; @@ -5474,9 +5473,9 @@ namespace ts { return result; function getDefinition(symbol: Symbol): DefinitionInfo { - let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); - let name = map(info.displayParts, p => p.text).join(""); - let declarations = symbol.declarations; + const info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); + const name = map(info.displayParts, p => p.text).join(""); + const declarations = symbol.declarations; if (!declarations || declarations.length === 0) { return undefined; } @@ -5506,7 +5505,7 @@ namespace ts { // Try to get the local symbol if we're dealing with an 'export default' // since that symbol has the "true" name. - let localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); + const localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); symbol = localExportDefaultSymbol || symbol; return stripQuotes(symbol.name); @@ -5523,14 +5522,14 @@ namespace ts { function getSymbolScope(symbol: Symbol): Node { // If this is the symbol of a named function expression or named class expression, // then named references are limited to its own scope. - let valueDeclaration = symbol.valueDeclaration; + const valueDeclaration = symbol.valueDeclaration; if (valueDeclaration && (valueDeclaration.kind === SyntaxKind.FunctionExpression || valueDeclaration.kind === SyntaxKind.ClassExpression)) { return valueDeclaration; } // If this is private property or method, the scope is the containing class if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) { - let privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); + const privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } @@ -5548,12 +5547,12 @@ namespace ts { return undefined; } - let scope: Node = undefined; + let scope: Node; - let declarations = symbol.getDeclarations(); + const declarations = symbol.getDeclarations(); if (declarations) { - for (let declaration of declarations) { - let container = getContainerNode(declaration); + for (const declaration of declarations) { + const container = getContainerNode(declaration); if (!container) { return undefined; @@ -5579,7 +5578,7 @@ namespace ts { } function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, start: number, end: number): number[] { - let positions: number[] = []; + const positions: number[] = []; /// TODO: Cache symbol existence for files to save text search // Also, need to make this work for unicode escapes. @@ -5589,9 +5588,9 @@ namespace ts { return positions; } - let text = sourceFile.text; - let sourceLength = text.length; - let symbolNameLength = symbolName.length; + const text = sourceFile.text; + const sourceLength = text.length; + const symbolNameLength = symbolName.length; let position = text.indexOf(symbolName, start); while (position >= 0) { @@ -5602,7 +5601,7 @@ namespace ts { // We found a match. Make sure it's not part of a larger word (i.e. the char // before and after it have to be a non-identifier char). - let endPosition = position + symbolNameLength; + const endPosition = position + symbolNameLength; if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) && (endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) { @@ -5616,14 +5615,14 @@ namespace ts { } function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferencedSymbol[] { - let references: ReferenceEntry[] = []; - let sourceFile = container.getSourceFile(); - let labelName = targetLabel.text; - let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); + const references: ReferenceEntry[] = []; + const sourceFile = container.getSourceFile(); + const labelName = targetLabel.text; + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || node.getWidth() !== labelName.length) { return; } @@ -5635,14 +5634,14 @@ namespace ts { } }); - let definition: DefinitionInfo = { + const definition: DefinitionInfo = { containerKind: "", containerName: "", fileName: targetLabel.getSourceFile().fileName, kind: ScriptElementKind.label, name: labelName, textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()) - } + }; return [{ definition, references }]; } @@ -5687,19 +5686,19 @@ namespace ts { result: ReferencedSymbol[], symbolToIndex: number[]): void { - let sourceFile = container.getSourceFile(); - let tripleSlashDirectivePrefixRegex = /^\/\/\/\s* { cancellationToken.throwIfCancellationRequested(); - let referenceLocation = getTouchingPropertyName(sourceFile, position); + const referenceLocation = getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, searchText)) { // This wasn't the start of a token. Check to see if it might be a // match in a comment or string if that's what the caller is asking @@ -5727,14 +5726,14 @@ namespace ts { return; } - let referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); + const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); if (referenceSymbol) { - let referenceSymbolDeclaration = referenceSymbol.valueDeclaration; - let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); - let relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); + const referenceSymbolDeclaration = referenceSymbol.valueDeclaration; + const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); + const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); if (relatedSymbol) { - let referencedSymbol = getReferencedSymbol(relatedSymbol); + const referencedSymbol = getReferencedSymbol(relatedSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation)); } /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment @@ -5744,7 +5743,7 @@ namespace ts { * position of property accessing, the referenceEntry of such position will be handled in the first case. */ else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) { - let referencedSymbol = getReferencedSymbol(shorthandValueSymbol); + const referencedSymbol = getReferencedSymbol(shorthandValueSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); } } @@ -5754,7 +5753,7 @@ namespace ts { return; function getReferencedSymbol(symbol: Symbol): ReferencedSymbol { - let symbolId = getSymbolId(symbol); + const symbolId = getSymbolId(symbol); let index = symbolToIndex[symbolId]; if (index === undefined) { index = result.length; @@ -5773,7 +5772,7 @@ namespace ts { return isInCommentHelper(sourceFile, position, isNonReferenceComment); function isNonReferenceComment(c: CommentRange): boolean { - let commentText = sourceFile.text.substring(c.pos, c.end); + const commentText = sourceFile.text.substring(c.pos, c.end); return !tripleSlashDirectivePrefixRegex.test(commentText); } } @@ -5802,20 +5801,20 @@ namespace ts { return undefined; } - let references: ReferenceEntry[] = []; + const references: ReferenceEntry[] = []; - let sourceFile = searchSpaceNode.getSourceFile(); - let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + const sourceFile = searchSpaceNode.getSourceFile(); + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || node.kind !== SyntaxKind.SuperKeyword) { return; } - let container = getSuperContainer(node, /*includeFunctions*/ false); + const container = getSuperContainer(node, /*includeFunctions*/ false); // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space @@ -5825,7 +5824,7 @@ namespace ts { } }); - let definition = getDefinition(searchSpaceNode.symbol); + const definition = getDefinition(searchSpaceNode.symbol); return [{ definition, references }]; } @@ -5847,7 +5846,7 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - staticFlag &= searchSpaceNode.flags + staticFlag &= searchSpaceNode.flags; searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; case SyntaxKind.SourceFile: @@ -5864,7 +5863,7 @@ namespace ts { return undefined; } - let references: ReferenceEntry[] = []; + const references: ReferenceEntry[] = []; let possiblePositions: number[]; if (searchSpaceNode.kind === SyntaxKind.SourceFile) { @@ -5874,7 +5873,7 @@ namespace ts { }); } else { - let sourceFile = searchSpaceNode.getSourceFile(); + const sourceFile = searchSpaceNode.getSourceFile(); possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); } @@ -5895,12 +5894,12 @@ namespace ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || (node.kind !== SyntaxKind.ThisKeyword && node.kind !== SyntaxKind.ThisType)) { return; } - let container = getThisContainer(node, /* includeArrowFunctions */ false); + const container = getThisContainer(node, /* includeArrowFunctions */ false); switch (searchSpaceNode.kind) { case SyntaxKind.FunctionExpression: @@ -5935,7 +5934,7 @@ namespace ts { function populateSearchSymbolSet(symbol: Symbol, location: Node): Symbol[] { // The search set contains at least the current symbol - let result = [symbol]; + const result = [symbol]; // If the symbol is an alias, add what it alaises to the list if (isImportOrExportSpecifierImportSymbol(symbol)) { @@ -5955,13 +5954,13 @@ namespace ts { * property name and variable declaration of the identifier. * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service * should show both 'name' in 'obj' and 'name' in variable declaration - * let name = "Foo"; - * let obj = { name }; + * const name = "Foo"; + * const obj = { name }; * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration * will be included correctly. */ - let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); + const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); if (shorthandValueSymbol) { result.push(shorthandValueSymbol); } @@ -5999,9 +5998,9 @@ namespace ts { function getPropertySymbolFromTypeReference(typeReference: ExpressionWithTypeArguments) { if (typeReference) { - let type = typeChecker.getTypeAtLocation(typeReference); + const type = typeChecker.getTypeAtLocation(typeReference); if (type) { - let propertySymbol = typeChecker.getPropertyOfType(type, propertyName); + const propertySymbol = typeChecker.getPropertyOfType(type, propertyName); if (propertySymbol) { result.push(propertySymbol); } @@ -6021,7 +6020,7 @@ namespace ts { // If the reference symbol is an alias, check if what it is aliasing is one of the search // symbols. if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) { - let aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); + const aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); if (searchSymbols.indexOf(aliasedSymbol) >= 0) { return aliasedSymbol; } @@ -6047,7 +6046,7 @@ namespace ts { // Finally, try all properties with the same name in any type the containing type extended or implemented, and // see if any is in the list if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - let result: Symbol[] = []; + const result: Symbol[] = []; getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } @@ -6058,21 +6057,21 @@ namespace ts { function getPropertySymbolsFromContextualType(node: Node): Symbol[] { if (isNameOfPropertyAssignment(node)) { - let objectLiteral = node.parent.parent; - let contextualType = typeChecker.getContextualType(objectLiteral); - let name = (node).text; + const objectLiteral = node.parent.parent; + const contextualType = typeChecker.getContextualType(objectLiteral); + const name = (node).text; if (contextualType) { if (contextualType.flags & TypeFlags.Union) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - let unionProperty = contextualType.getProperty(name) + const unionProperty = contextualType.getProperty(name); if (unionProperty) { return [unionProperty]; } else { - let result: Symbol[] = []; + const result: Symbol[] = []; forEach((contextualType).types, t => { - let symbol = t.getProperty(name); + const symbol = t.getProperty(name); if (symbol) { result.push(symbol); } @@ -6081,7 +6080,7 @@ namespace ts { } } else { - let symbol = contextualType.getProperty(name); + const symbol = contextualType.getProperty(name); if (symbol) { return [symbol]; } @@ -6110,8 +6109,8 @@ namespace ts { // Remember the last meaning lastIterationMeaning = meaning; - for (let declaration of declarations) { - let declarationMeaning = getMeaningFromDeclaration(declaration); + for (const declaration of declarations) { + const declarationMeaning = getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -6146,13 +6145,13 @@ namespace ts { return true; } - let parent = node.parent; + const parent = node.parent; if (parent) { if (parent.kind === SyntaxKind.PostfixUnaryExpression || parent.kind === SyntaxKind.PrefixUnaryExpression) { return true; } else if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { - let operator = (parent).operatorToken.kind; + const operator = (parent).operatorToken.kind; return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment; } } @@ -6174,8 +6173,8 @@ namespace ts { function getEmitOutput(fileName: string): EmitOutput { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let outputFiles: OutputFile[] = []; + const sourceFile = getValidSourceFile(fileName); + const outputFiles: OutputFile[] = []; function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) { outputFiles.push({ @@ -6185,7 +6184,7 @@ namespace ts { }); } - let emitOutput = program.emit(sourceFile, writeFile, cancellationToken); + const emitOutput = program.emit(sourceFile, writeFile, cancellationToken); return { outputFiles, @@ -6278,7 +6277,7 @@ namespace ts { } if (!isLastClause && root.parent.kind === SyntaxKind.ExpressionWithTypeArguments && root.parent.parent.kind === SyntaxKind.HeritageClause) { - let decl = root.parent.parent.parent; + const decl = root.parent.parent.parent; return (decl.kind === SyntaxKind.ClassDeclaration && (root.parent.parent).token === SyntaxKind.ImplementsKeyword) || (decl.kind === SyntaxKind.InterfaceDeclaration && (root.parent.parent).token === SyntaxKind.ExtendsKeyword); } @@ -6350,7 +6349,7 @@ namespace ts { function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); return SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken); } @@ -6361,10 +6360,10 @@ namespace ts { } function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location - let node = getTouchingPropertyName(sourceFile, startPos); + const node = getTouchingPropertyName(sourceFile, startPos); if (!node) { return; @@ -6420,13 +6419,13 @@ namespace ts { function getBreakpointStatementAtPosition(fileName: string, position: number) { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } function getNavigationBarItems(fileName: string): NavigationBarItem[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return NavigationBar.getNavigationBarItems(sourceFile, host.getCompilationSettings()); } @@ -6458,11 +6457,11 @@ namespace ts { function getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let typeChecker = program.getTypeChecker(); + const sourceFile = getValidSourceFile(fileName); + const typeChecker = program.getTypeChecker(); - let result: number[] = []; - let classifiableNames = program.getClassifiableNames(); + const result: number[] = []; + const classifiableNames = program.getClassifiableNames(); processNode(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6474,7 +6473,7 @@ namespace ts { } function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning): ClassificationType { - let flags = symbol.getFlags(); + const flags = symbol.getFlags(); if ((flags & SymbolFlags.Classifiable) === SymbolFlags.None) { return; } @@ -6522,19 +6521,19 @@ namespace ts { function processNode(node: Node) { // Only walk into nodes that intersect the requested span. if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { - let kind = node.kind; + const kind = node.kind; checkForClassificationCancellation(kind); if (kind === SyntaxKind.Identifier && !nodeIsMissing(node)) { - let identifier = node; + const identifier = node; // Only bother calling into the typechecker if this is an identifier that // could possibly resolve to a type name. This makes classification run // in a third of the time it would normally take. if (classifiableNames[identifier.text]) { - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (symbol) { - let type = classifySymbol(symbol, getMeaningFromLocation(node)); + const type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { pushClassification(node.getStart(), node.getWidth(), type); } @@ -6574,8 +6573,8 @@ namespace ts { function convertClassifications(classifications: Classifications): ClassifiedSpan[] { Debug.assert(classifications.spans.length % 3 === 0); - let dense = classifications.spans; - let result: ClassifiedSpan[] = []; + const dense = classifications.spans; + const result: ClassifiedSpan[] = []; for (let i = 0, n = dense.length; i < n; i += 3) { result.push({ textSpan: createTextSpan(dense[i], dense[i + 1]), @@ -6592,15 +6591,15 @@ namespace ts { function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - let spanStart = span.start; - let spanLength = span.length; + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const spanStart = span.start; + const spanLength = span.length; // Make a scanner we can get trivia from. - let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); - let mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); + const triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + const mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - let result: number[] = []; + const result: number[] = []; processElement(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6614,15 +6613,15 @@ namespace ts { function classifyLeadingTriviaAndGetTokenStart(token: Node): number { triviaScanner.setTextPos(token.pos); while (true) { - let start = triviaScanner.getTextPos(); + const start = triviaScanner.getTextPos(); // only bother scanning if we have something that could be trivia. if (!couldStartTrivia(sourceFile.text, start)) { return start; } - let kind = triviaScanner.scan(); - let end = triviaScanner.getTextPos(); - let width = end - start; + const kind = triviaScanner.scan(); + const end = triviaScanner.getTextPos(); + const width = end - start; // The moment we get something that isn't trivia, then stop processing. if (!isTrivia(kind)) { @@ -6646,8 +6645,8 @@ namespace ts { } if (kind === SyntaxKind.ConflictMarkerTrivia) { - let text = sourceFile.text; - let ch = text.charCodeAt(start); + const text = sourceFile.text; + const ch = text.charCodeAt(start); // for the <<<<<<< and >>>>>>> markers, we just add them in as comments // in the classification stream. @@ -6668,7 +6667,7 @@ namespace ts { if (kind === SyntaxKind.MultiLineCommentTrivia) { // See if this is a doc comment. If so, we'll classify certain portions of it // specially. - let docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); + const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDocComment) { docCommentAndDiagnostics.jsDocComment.parent = token; classifyJSDocComment(docCommentAndDiagnostics.jsDocComment); @@ -6687,7 +6686,7 @@ namespace ts { function classifyJSDocComment(docComment: JSDocComment) { let pos = docComment.pos; - for (let tag of docComment.tags) { + for (const tag of docComment.tags) { // As we walk through each tag, classify the portion of text from the end of // the last tag (or the start of the entire doc comment) as 'comment'. if (tag.pos !== pos) { @@ -6745,7 +6744,7 @@ namespace ts { } function processJSDocTemplateTag(tag: JSDocTemplateTag) { - for (let child of tag.getChildren()) { + for (const child of tag.getChildren()) { processElement(child); } } @@ -6767,11 +6766,11 @@ namespace ts { } function classifyDisabledCodeToken() { - let start = mergeConflictScanner.getTextPos(); - let tokenKind = mergeConflictScanner.scan(); - let end = mergeConflictScanner.getTextPos(); + const start = mergeConflictScanner.getTextPos(); + const tokenKind = mergeConflictScanner.scan(); + const end = mergeConflictScanner.getTextPos(); - let type = classifyTokenType(tokenKind); + const type = classifyTokenType(tokenKind); if (type) { pushClassification(start, end - start, type); } @@ -6782,12 +6781,12 @@ namespace ts { return; } - let tokenStart = classifyLeadingTriviaAndGetTokenStart(token); + const tokenStart = classifyLeadingTriviaAndGetTokenStart(token); - let tokenWidth = token.end - tokenStart; + const tokenWidth = token.end - tokenStart; Debug.assert(tokenWidth >= 0); if (tokenWidth > 0) { - let type = classifyTokenType(token.kind, token); + const type = classifyTokenType(token.kind, token); if (type) { pushClassification(tokenStart, tokenWidth, type); } @@ -6914,9 +6913,9 @@ namespace ts { if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { checkForClassificationCancellation(element.kind); - let children = element.getChildren(sourceFile); + const children = element.getChildren(sourceFile); for (let i = 0, n = children.length; i < n; i++) { - let child = children[i]; + const child = children[i]; if (isToken(child)) { classifyToken(child); } @@ -6931,28 +6930,28 @@ namespace ts { function getOutliningSpans(fileName: string): OutliningSpan[] { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return OutliningElementsCollector.collectElements(sourceFile); } function getBraceMatchingAtPosition(fileName: string, position: number) { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - let result: TextSpan[] = []; + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const result: TextSpan[] = []; - let token = getTouchingToken(sourceFile, position); + const token = getTouchingToken(sourceFile, position); if (token.getStart(sourceFile) === position) { - let matchKind = getMatchingTokenKind(token); + const matchKind = getMatchingTokenKind(token); // Ensure that there is a corresponding token to match ours. if (matchKind) { - let parentElement = token.parent; + const parentElement = token.parent; - let childNodes = parentElement.getChildren(sourceFile); - for (let current of childNodes) { + const childNodes = parentElement.getChildren(sourceFile); + for (const current of childNodes) { if (current.kind === matchKind) { - let range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); - let range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); + const range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); + const range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); // We want to order the braces when we return the result. if (range1.start < range2.start) { @@ -6972,11 +6971,11 @@ namespace ts { function getMatchingTokenKind(token: Node): ts.SyntaxKind { switch (token.kind) { - case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken + case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken; case ts.SyntaxKind.OpenParenToken: return ts.SyntaxKind.CloseParenToken; case ts.SyntaxKind.OpenBracketToken: return ts.SyntaxKind.CloseBracketToken; case ts.SyntaxKind.LessThanToken: return ts.SyntaxKind.GreaterThanToken; - case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken + case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken; case ts.SyntaxKind.CloseParenToken: return ts.SyntaxKind.OpenParenToken; case ts.SyntaxKind.CloseBracketToken: return ts.SyntaxKind.OpenBracketToken; case ts.SyntaxKind.GreaterThanToken: return ts.SyntaxKind.LessThanToken; @@ -6988,29 +6987,29 @@ namespace ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { let start = new Date().getTime(); - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); start = new Date().getTime(); - let result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); + const result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start)); return result; } function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); } function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatDocument(sourceFile, getRuleProvider(options), options); } function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); if (key === "}") { return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options); @@ -7046,16 +7045,16 @@ namespace ts { * be performed. */ function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { - let start = new Date().getTime(); - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const start = new Date().getTime(); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Check if in a context where we don't want to perform any insertion if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { return undefined; } - let tokenAtPos = getTokenAtPosition(sourceFile, position); - let tokenStart = tokenAtPos.getStart() + const tokenAtPos = getTokenAtPosition(sourceFile, position); + const tokenStart = tokenAtPos.getStart(); if (!tokenAtPos || tokenStart < position) { return undefined; } @@ -7091,11 +7090,11 @@ namespace ts { return undefined; } - let parameters = getParametersForJsDocOwningNode(commentOwner); - let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); - let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + const parameters = getParametersForJsDocOwningNode(commentOwner); + const posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + const lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; - let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); // TODO: call a helper method instead once PR #4133 gets merged in. const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; @@ -7119,7 +7118,7 @@ namespace ts { // * if the caret was directly in front of the object, then we add an extra line and indentation. const preamble = "/**" + newLine + indentationStr + " * "; - let result = + const result = preamble + newLine + docParams + indentationStr + " */" + @@ -7163,7 +7162,7 @@ namespace ts { case SyntaxKind.ArrowFunction: return (rightHandSide).parameters; case SyntaxKind.ClassExpression: - for (let member of (rightHandSide).members) { + for (const member of (rightHandSide).members) { if (member.kind === SyntaxKind.Constructor) { return (member).parameters; } @@ -7183,15 +7182,15 @@ namespace ts { // anything away. synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); - let fileContents = sourceFile.text; - let result: TodoComment[] = []; + const fileContents = sourceFile.text; + const result: TodoComment[] = []; if (descriptors.length > 0) { - let regExp = getTodoCommentsRegExp(); + const regExp = getTodoCommentsRegExp(); let matchArray: RegExpExecArray; while (matchArray = regExp.exec(fileContents)) { @@ -7214,15 +7213,15 @@ namespace ts { // // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. // "hack" in position 4 means HACK did match. - let firstDescriptorCaptureIndex = 3; + const firstDescriptorCaptureIndex = 3; Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); - let preamble = matchArray[1]; - let matchPosition = matchArray.index + preamble.length; + const preamble = matchArray[1]; + const matchPosition = matchArray.index + preamble.length; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. - let token = getTokenAtPosition(sourceFile, matchPosition); + const token = getTokenAtPosition(sourceFile, matchPosition); if (!isInsideComment(sourceFile, token, matchPosition)) { continue; } @@ -7241,7 +7240,7 @@ namespace ts { continue; } - let message = matchArray[2]; + const message = matchArray[2]; result.push({ descriptor: descriptor, message: message, @@ -7272,14 +7271,14 @@ namespace ts { // // The following three regexps are used to match the start of the text up to the TODO // comment portion. - let singleLineCommentStart = /(?:\/\/+\s*)/.source; - let multiLineCommentStart = /(?:\/\*+\s*)/.source; - let anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; + const singleLineCommentStart = /(?:\/\/+\s*)/.source; + const multiLineCommentStart = /(?:\/\*+\s*)/.source; + const anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; // Match any of the above three TODO comment start regexps. // Note that the outermost group *is* a capture group. We want to capture the preamble // so that we can determine the starting position of the TODO comment match. - let preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; + const preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; // Takes the descriptors and forms a regexp that matches them as if they were literals. // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: @@ -7289,17 +7288,17 @@ namespace ts { // Note that the outermost group is *not* a capture group, but the innermost groups // *are* capture groups. By capturing the inner literals we can determine after // matching which descriptor we are dealing with. - let literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; + const literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; // After matching a descriptor literal, the following regexp matches the rest of the // text up to the end of the line (or */). - let endOfLineOrEndOfComment = /(?:$|\*\/)/.source - let messageRemainder = /(?:.*?)/.source + const endOfLineOrEndOfComment = /(?:$|\*\/)/.source; + const messageRemainder = /(?:.*?)/.source; // This is the portion of the match we'll return as part of the TODO comment result. We // match the literal portion up to the end of the line or end of comment. - let messagePortion = "(" + literals + messageRemainder + ")"; - let regExpString = preamble + messagePortion + endOfLineOrEndOfComment; + const messagePortion = "(" + literals + messageRemainder + ")"; + const regExpString = preamble + messagePortion + endOfLineOrEndOfComment; // The final regexp will look like this: // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim @@ -7325,40 +7324,40 @@ namespace ts { function getRenameInfo(fileName: string, position: number): RenameInfo { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let typeChecker = program.getTypeChecker(); + const sourceFile = getValidSourceFile(fileName); + const typeChecker = program.getTypeChecker(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); // Can only rename an identifier. if (node && node.kind === SyntaxKind.Identifier) { - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); // Only allow a symbol to be renamed if it actually has at least one declaration. if (symbol) { - let declarations = symbol.getDeclarations(); + const declarations = symbol.getDeclarations(); if (declarations && declarations.length > 0) { // Disallow rename for elements that are defined in the standard TypeScript library. - let defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); + const defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); if (defaultLibFileName) { - for (let current of declarations) { - let sourceFile = current.getSourceFile(); - var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); + for (const current of declarations) { + const sourceFile = current.getSourceFile(); + const canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); if (sourceFile && getCanonicalFileName(ts.normalizePath(sourceFile.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) { return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); } } } - let displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); - let kind = getSymbolKind(symbol, node); + const displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const kind = getSymbolKind(symbol, node); if (kind) { return { canRename: true, - localizedErrorMessage: undefined, + kind, displayName, + localizedErrorMessage: undefined, fullDisplayName: typeChecker.getFullyQualifiedName(symbol), - kind: kind, kindModifiers: getSymbolModifiers(symbol), triggerSpan: createTextSpan(node.getStart(), node.getWidth()) }; @@ -7425,14 +7424,14 @@ namespace ts { /* @internal */ export function getNameTable(sourceFile: SourceFile): Map { if (!sourceFile.nameTable) { - initializeNameTable(sourceFile) + initializeNameTable(sourceFile); } return sourceFile.nameTable; } function initializeNameTable(sourceFile: SourceFile): void { - let nameTable: Map = {}; + const nameTable: Map = {}; walk(sourceFile); sourceFile.nameTable = nameTable; @@ -7470,13 +7469,13 @@ namespace ts { /// Classifier export function createClassifier(): Classifier { - let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); + const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); /// We do not have a full parser support to know when we should parse a regex or not /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where /// we have a series of divide operator. this list allows us to be more accurate by ruling out /// locations where a regexp cannot exist. - let noRegexTable: boolean[] = []; + const noRegexTable: boolean[] = []; noRegexTable[SyntaxKind.Identifier] = true; noRegexTable[SyntaxKind.StringLiteral] = true; noRegexTable[SyntaxKind.NumericLiteral] = true; @@ -7510,7 +7509,7 @@ namespace ts { // // Where on the second line, you will get the 'return' keyword, // a string literal, and a template end consisting of '} } `'. - let templateStack: SyntaxKind[] = []; + const templateStack: SyntaxKind[] = []; /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind) { @@ -7536,18 +7535,18 @@ namespace ts { } function convertClassifications(classifications: Classifications, text: string): ClassificationResult { - let entries: ClassificationInfo[] = []; - let dense = classifications.spans; + const entries: ClassificationInfo[] = []; + const dense = classifications.spans; let lastEnd = 0; for (let i = 0, n = dense.length; i < n; i += 3) { - let start = dense[i]; - let length = dense[i + 1]; - let type = dense[i + 2]; + const start = dense[i]; + const length = dense[i + 1]; + const type = dense[i + 2]; // Make a whitespace entry between the last item and this one. if (lastEnd >= 0) { - let whitespaceLength = start - lastEnd; + const whitespaceLength = start - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7557,7 +7556,7 @@ namespace ts { lastEnd = start + length; } - let whitespaceLength = text.length - lastEnd; + const whitespaceLength = text.length - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7611,7 +7610,7 @@ namespace ts { // (and a newline). That way when we lex we'll think we're still in a multiline comment. switch (lexState) { case EndOfLineState.InDoubleQuoteStringLiteral: - text = '"\\\n' + text; + text = "\"\\\n" + text; offset = 3; break; case EndOfLineState.InSingleQuoteStringLiteral: @@ -7637,7 +7636,7 @@ namespace ts { scanner.setText(text); - let result: Classifications = { + const result: Classifications = { endOfLineState: EndOfLineState.None, spans: [] }; @@ -7719,7 +7718,7 @@ namespace ts { // If we don't have anything on the template stack, // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { - let lastTemplateStackToken = lastOrUndefined(templateStack); + const lastTemplateStackToken = lastOrUndefined(templateStack); if (lastTemplateStackToken === SyntaxKind.TemplateHead) { token = scanner.reScanTemplateToken(); @@ -7749,17 +7748,17 @@ namespace ts { return result; function processToken(): void { - let start = scanner.getTokenPos(); - let end = scanner.getTextPos(); + const start = scanner.getTokenPos(); + const end = scanner.getTextPos(); addResult(start, end, classFromKind(token)); if (end >= text.length) { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.StringLiteralType) { // Check to see if we finished up on a multiline string literal. - let tokenText = scanner.getTokenText(); + const tokenText = scanner.getTokenText(); if (scanner.isUnterminated()) { - let lastCharIndex = tokenText.length - 1; + const lastCharIndex = tokenText.length - 1; let numBackslashes = 0; while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) { @@ -7768,7 +7767,7 @@ namespace ts { // If we have an odd number of backslashes, then the multiline string is unclosed if (numBackslashes & 1) { - let quoteChar = tokenText.charCodeAt(0); + const quoteChar = tokenText.charCodeAt(0); result.endOfLineState = quoteChar === CharacterCodes.doubleQuote ? EndOfLineState.InDoubleQuoteStringLiteral : EndOfLineState.InSingleQuoteStringLiteral; @@ -7817,7 +7816,7 @@ namespace ts { // relative to the original text. start -= offset; end -= offset; - let length = end - start; + const length = end - start; if (length > 0) { result.spans.push(start); @@ -7932,7 +7931,7 @@ namespace ts { } /// getDefaultLibraryFilePath - declare let __dirname: string; + declare const __dirname: string; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript From a2b6e8c2c0f6e5bf9ac259c16b399791e3f1ca13 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 15 Dec 2015 11:39:54 -0800 Subject: [PATCH 21/24] Use nicer flag collection method --- src/compiler/checker.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 09760b6b1e5..0700a82a6b8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3766,13 +3766,14 @@ namespace ts { function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol { const types = containingType.types; let props: Symbol[]; - let isOptional = !!(containingType.flags & TypeFlags.Intersection); + // Flags we want to propagate to the result if they exist in all source symbols + let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None; for (const current of types) { const type = getApparentType(current); if (type !== unknownType) { const prop = getPropertyOfType(type, name); if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) { - isOptional = isOptional && !!(prop.flags & SymbolFlags.Optional); + commonFlags &= prop.flags; if (!props) { props = [prop]; } @@ -3804,7 +3805,7 @@ namespace ts { SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | - (isOptional ? SymbolFlags.Optional : SymbolFlags.None), + commonFlags, name); result.containingType = containingType; result.declarations = declarations; From d8db60a9a2be9c4ca82170bc6bb457b70b20f7b5 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 15 Dec 2015 17:52:26 -0800 Subject: [PATCH 22/24] Use a comparison function instead of creating a new type for each signature. --- src/compiler/checker.ts | 125 ++++++++++++++++++++++++++++++---------- src/compiler/types.ts | 2 - 2 files changed, 94 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fac21177aae..e1b400310b5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3501,7 +3501,7 @@ namespace ts { function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreReturnTypes: boolean): Signature { for (const s of signatureList) { - if (compareSignatures(s, signature, partialMatch, ignoreReturnTypes, compareTypes)) { + if (compareSignaturesIdentical(s, signature, partialMatch, ignoreReturnTypes, compareTypesIdentical)) { return s; } } @@ -4115,16 +4115,6 @@ namespace ts { return signature.erasedSignatureCache; } - function getAnyReturningErasedSignature(signature: Signature): Signature { - if (!signature.anyReturningErasedSignatureCache) { - const erasedSignature = getErasedSignature(signature); - const anyReturningErasedSignature = cloneSignature(erasedSignature); - anyReturningErasedSignature.resolvedReturnType = anyType; - signature.anyReturningErasedSignatureCache = anyReturningErasedSignature; - } - return signature.anyReturningErasedSignatureCache; - } - function getOrCreateTypeFromSignature(signature: Signature): ObjectType { // There are two ways to declare a construct signature, one is by declaring a class constructor // using the constructor keyword, and the other is declaring a bare construct signature in an @@ -4965,7 +4955,7 @@ namespace ts { return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined); } - function compareTypes(source: Type, target: Type): Ternary { + function compareTypesIdentical(source: Type, target: Type): Ternary { return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined) ? Ternary.True : Ternary.False; } @@ -4985,10 +4975,53 @@ namespace ts { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain); } - function isSignatureAssignableTo(source: Signature, target: Signature): boolean { - const sourceType = getOrCreateTypeFromSignature(source); - const targetType = getOrCreateTypeFromSignature(target); - return checkTypeRelatedTo(sourceType, targetType, assignableRelation, /*errorNode*/ undefined); + /** + * See signatureRelatedTo, compareSignaturesIdentical + */ + function isSignatureAssignableTo(source: Signature, target: Signature, ignoreReturnTypes: boolean): boolean { + // TODO (drosen): De-duplicate code between related functions. + if (source === target) { + return true; + } + if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) { + return false; + } + + // Spec 1.0 Section 3.8.3 & 3.8.4: + // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N + source = getErasedSignature(source); + target = getErasedSignature(target); + + const sourceMax = getNumNonRestParameters(source); + const targetMax = getNumNonRestParameters(target); + const checkCount = getNumParametersToCheckForSignatureRelatability(source, sourceMax, target, targetMax); + for (let i = 0; i < checkCount; i++) { + const s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); + const t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + const related = isTypeAssignableTo(t, s) || isTypeAssignableTo(s, t); + if (!related) { + return false; + } + } + + if (!ignoreReturnTypes) { + const targetReturnType = getReturnTypeOfSignature(target); + if (targetReturnType === voidType) { + return true; + } + const sourceReturnType = getReturnTypeOfSignature(source); + + // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions + if (targetReturnType.flags & TypeFlags.PredicateType && (targetReturnType as PredicateType).predicate.kind === TypePredicateKind.Identifier) { + if (!(sourceReturnType.flags & TypeFlags.PredicateType)) { + return false; + } + } + + return isTypeAssignableTo(sourceReturnType, targetReturnType); + } + + return true; } function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean { @@ -5002,15 +5035,35 @@ namespace ts { || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined) || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined)) { - // The return types are compatible, so create versions of the signature with 'any' as the return type. - // We need to do this so that we can check assignability while disregarding the return type. - const anyReturningSource = getAnyReturningErasedSignature(implementation); - const anyReturningTarget = getAnyReturningErasedSignature(overload); + return isSignatureAssignableTo(erasedSource, erasedTarget, /*ignoreReturnTypes*/ true); + } - // Create object types to actually perform relation checks. - const anyReturningSourceType = getOrCreateTypeFromSignature(anyReturningSource); - const anyReturningTargetType = getOrCreateTypeFromSignature(anyReturningTarget); - return checkTypeRelatedTo(anyReturningSourceType, anyReturningTargetType, assignableRelation, /*errorNode*/ undefined); + return false; + } + + function getNumNonRestParameters(signature: Signature) { + const numParams = signature.parameters.length; + return signature.hasRestParameter ? + numParams - 1 : + numParams; + } + + function getNumParametersToCheckForSignatureRelatability(source: Signature, sourceNonRestParamCount: number, target: Signature, targetNonRestParamCount: number) { + if (source.hasRestParameter === target.hasRestParameter) { + if (source.hasRestParameter) { + // If both have rest parameters, get the max and add 1 to + // compensate for the rest parameter. + return Math.max(sourceNonRestParamCount, targetNonRestParamCount) + 1; + } + else { + return Math.min(sourceNonRestParamCount, targetNonRestParamCount); + } + } + else { + // Return the count for whichever signature doesn't have rest parameters. + return source.hasRestParameter ? + targetNonRestParamCount : + sourceNonRestParamCount; } } @@ -5645,7 +5698,11 @@ namespace ts { } } + /** + * See signatureAssignableTo, signatureAssignableTo + */ function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary { + // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; } @@ -5697,10 +5754,12 @@ namespace ts { } const targetReturnType = getReturnTypeOfSignature(target); - if (targetReturnType === voidType) return result; + if (targetReturnType === voidType) { + return result; + } const sourceReturnType = getReturnTypeOfSignature(source); - // The follow block preserves old behavior forbidding boolean returning functions from being assignable to type guard returning functions + // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions if (targetReturnType.flags & TypeFlags.PredicateType && (targetReturnType as PredicateType).predicate.kind === TypePredicateKind.Identifier) { if (!(sourceReturnType.flags & TypeFlags.PredicateType)) { if (reportErrors) { @@ -5721,7 +5780,7 @@ namespace ts { } let result = Ternary.True; for (let i = 0, len = sourceSignatures.length; i < len; ++i) { - const related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); + const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { return Ternary.False; } @@ -5833,7 +5892,7 @@ namespace ts { } function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean { - return compareProperties(sourceProp, targetProp, compareTypes) !== Ternary.False; + return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False; } function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary { @@ -5880,7 +5939,11 @@ namespace ts { return false; } - function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + /** + * See signatureRelatedTo, compareSignaturesIdentical + */ + function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; } @@ -7571,7 +7634,7 @@ namespace ts { // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignatures(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypes)) { + else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { // Signatures aren't identical, do not use return undefined; } @@ -11564,7 +11627,7 @@ namespace ts { } for (const otherSignature of signaturesToCheck) { - if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature)) { + if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature, /*ignoreReturnTypes*/ false)) { return; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c6c78709300..ff8ffa4ebd2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2280,8 +2280,6 @@ namespace ts { /* @internal */ erasedSignatureCache?: Signature; // Erased version of signature (deferred) /* @internal */ - anyReturningErasedSignatureCache?: Signature; // A version of the erased signature whose type returns 'any' - /* @internal */ isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison } From 731925bffeb356e3ee18628bc8d8997d6c79c83f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 15 Dec 2015 20:55:54 -0800 Subject: [PATCH 23/24] Fix linter nits. --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1b400310b5..c017f9e7921 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5040,7 +5040,7 @@ namespace ts { return false; } - + function getNumNonRestParameters(signature: Signature) { const numParams = signature.parameters.length; return signature.hasRestParameter ? @@ -5651,7 +5651,7 @@ namespace ts { shouldElaborateErrors = false; } } - // don't elaborate the primitive apparent types (like Number) + // don't elaborate the primitive apparent types (like Number) // because the actual primitives will have already been reported. if (shouldElaborateErrors && !isPrimitiveApparentType(source)) { reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1, From 2ec97a2d2e5ba40483f2e466ce414cb25e18314c Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 17 Dec 2015 18:00:53 -0800 Subject: [PATCH 24/24] Address PR feed back --- Jakefile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jakefile.js b/Jakefile.js index 91bd805a27b..288472a697b 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -925,7 +925,7 @@ var lintTargets = compilerSources .concat(harnessCoreSources) .concat(serverCoreSources) .concat(scriptSources) - .concat([path.join(servicesDirectory,"services.ts")]); + .concat([path.join(servicesDirectory, "services.ts")]); desc("Runs tslint on the compiler sources"); task("lint", ["build-rules"], function() {