From 116c87819a737c9c31d97989d1982444e2885727 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 2 Nov 2016 11:07:33 -0700 Subject: [PATCH 01/27] Test case for property used in destructuring variable declaration --- .../reference/unusedLocalProperty.errors.txt | 18 +++++++++++++ .../reference/unusedLocalProperty.js | 25 +++++++++++++++++++ tests/cases/compiler/unusedLocalProperty.ts | 12 +++++++++ 3 files changed, 55 insertions(+) create mode 100644 tests/baselines/reference/unusedLocalProperty.errors.txt create mode 100644 tests/baselines/reference/unusedLocalProperty.js create mode 100644 tests/cases/compiler/unusedLocalProperty.ts diff --git a/tests/baselines/reference/unusedLocalProperty.errors.txt b/tests/baselines/reference/unusedLocalProperty.errors.txt new file mode 100644 index 00000000000..c9a4b3cb6d9 --- /dev/null +++ b/tests/baselines/reference/unusedLocalProperty.errors.txt @@ -0,0 +1,18 @@ +tests/cases/compiler/unusedLocalProperty.ts(3,25): error TS6138: Property 'species' is declared but never used. + + +==== tests/cases/compiler/unusedLocalProperty.ts (1 errors) ==== + declare var console: { log(msg: any): void; } + class Animal { + constructor(private species: string) { + ~~~~~~~ +!!! error TS6138: Property 'species' is declared but never used. + } + + printSpecies() { + let { species } = this; + console.log(species); + } + } + + \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalProperty.js b/tests/baselines/reference/unusedLocalProperty.js new file mode 100644 index 00000000000..a124b752125 --- /dev/null +++ b/tests/baselines/reference/unusedLocalProperty.js @@ -0,0 +1,25 @@ +//// [unusedLocalProperty.ts] +declare var console: { log(msg: any): void; } +class Animal { + constructor(private species: string) { + } + + printSpecies() { + let { species } = this; + console.log(species); + } +} + + + +//// [unusedLocalProperty.js] +var Animal = (function () { + function Animal(species) { + this.species = species; + } + Animal.prototype.printSpecies = function () { + var species = this.species; + console.log(species); + }; + return Animal; +}()); diff --git a/tests/cases/compiler/unusedLocalProperty.ts b/tests/cases/compiler/unusedLocalProperty.ts new file mode 100644 index 00000000000..fdd33116135 --- /dev/null +++ b/tests/cases/compiler/unusedLocalProperty.ts @@ -0,0 +1,12 @@ +//@noUnusedLocals:true +declare var console: { log(msg: any): void; } +class Animal { + constructor(private species: string) { + } + + printSpecies() { + let { species } = this; + console.log(species); + } +} + From 13e8f7fadaa702bc871e98edc592c11a3d2c439a Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 2 Nov 2016 11:08:34 -0700 Subject: [PATCH 02/27] Mark property referenced in the destructuring as referenced Fixes #11324 --- src/compiler/checker.ts | 28 ++++++++++------- .../reference/unusedLocalProperty.errors.txt | 18 ----------- .../reference/unusedLocalProperty.symbols | 29 ++++++++++++++++++ .../reference/unusedLocalProperty.types | 30 +++++++++++++++++++ 4 files changed, 76 insertions(+), 29 deletions(-) delete mode 100644 tests/baselines/reference/unusedLocalProperty.errors.txt create mode 100644 tests/baselines/reference/unusedLocalProperty.symbols create mode 100644 tests/baselines/reference/unusedLocalProperty.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cf0c048ecbf..cfba4999212 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11504,6 +11504,21 @@ namespace ts { diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); } + function markPropertyAsReferenced(prop: Symbol) { + if (prop && + noUnusedIdentifiers && + (prop.flags & SymbolFlags.ClassMember) && + prop.valueDeclaration && (getModifierFlags(prop.valueDeclaration) & ModifierFlags.Private)) { + if (prop.flags & SymbolFlags.Instantiated) { + getSymbolLinks(prop).target.isReferenced = true; + + } + else { + prop.isReferenced = true; + } + } + } + function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { const type = checkNonNullExpression(left); if (isTypeAny(type) || type === silentNeverType) { @@ -11523,17 +11538,7 @@ namespace ts { return unknownType; } - if (noUnusedIdentifiers && - (prop.flags & SymbolFlags.ClassMember) && - prop.valueDeclaration && (getModifierFlags(prop.valueDeclaration) & ModifierFlags.Private)) { - if (prop.flags & SymbolFlags.Instantiated) { - getSymbolLinks(prop).target.isReferenced = true; - - } - else { - prop.isReferenced = true; - } - } + markPropertyAsReferenced(prop); getNodeLinks(node).resolvedSymbol = prop; @@ -16323,6 +16328,7 @@ namespace ts { const parentType = getTypeForBindingElementParent(parent); const name = node.propertyName || node.name; const property = getPropertyOfType(parentType, getTextOfPropertyName(name)); + markPropertyAsReferenced(property); if (parent.initializer && property && getParentOfSymbol(property)) { checkClassPropertyAccess(parent, parent.initializer, parentType, property); } diff --git a/tests/baselines/reference/unusedLocalProperty.errors.txt b/tests/baselines/reference/unusedLocalProperty.errors.txt deleted file mode 100644 index c9a4b3cb6d9..00000000000 --- a/tests/baselines/reference/unusedLocalProperty.errors.txt +++ /dev/null @@ -1,18 +0,0 @@ -tests/cases/compiler/unusedLocalProperty.ts(3,25): error TS6138: Property 'species' is declared but never used. - - -==== tests/cases/compiler/unusedLocalProperty.ts (1 errors) ==== - declare var console: { log(msg: any): void; } - class Animal { - constructor(private species: string) { - ~~~~~~~ -!!! error TS6138: Property 'species' is declared but never used. - } - - printSpecies() { - let { species } = this; - console.log(species); - } - } - - \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalProperty.symbols b/tests/baselines/reference/unusedLocalProperty.symbols new file mode 100644 index 00000000000..6a3343bd545 --- /dev/null +++ b/tests/baselines/reference/unusedLocalProperty.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/unusedLocalProperty.ts === +declare var console: { log(msg: any): void; } +>console : Symbol(console, Decl(unusedLocalProperty.ts, 0, 11)) +>log : Symbol(log, Decl(unusedLocalProperty.ts, 0, 22)) +>msg : Symbol(msg, Decl(unusedLocalProperty.ts, 0, 27)) + +class Animal { +>Animal : Symbol(Animal, Decl(unusedLocalProperty.ts, 0, 45)) + + constructor(private species: string) { +>species : Symbol(Animal.species, Decl(unusedLocalProperty.ts, 2, 16)) + } + + printSpecies() { +>printSpecies : Symbol(Animal.printSpecies, Decl(unusedLocalProperty.ts, 3, 5)) + + let { species } = this; +>species : Symbol(species, Decl(unusedLocalProperty.ts, 6, 13)) +>this : Symbol(Animal, Decl(unusedLocalProperty.ts, 0, 45)) + + console.log(species); +>console.log : Symbol(log, Decl(unusedLocalProperty.ts, 0, 22)) +>console : Symbol(console, Decl(unusedLocalProperty.ts, 0, 11)) +>log : Symbol(log, Decl(unusedLocalProperty.ts, 0, 22)) +>species : Symbol(species, Decl(unusedLocalProperty.ts, 6, 13)) + } +} + + diff --git a/tests/baselines/reference/unusedLocalProperty.types b/tests/baselines/reference/unusedLocalProperty.types new file mode 100644 index 00000000000..3cb8747957d --- /dev/null +++ b/tests/baselines/reference/unusedLocalProperty.types @@ -0,0 +1,30 @@ +=== tests/cases/compiler/unusedLocalProperty.ts === +declare var console: { log(msg: any): void; } +>console : { log(msg: any): void; } +>log : (msg: any) => void +>msg : any + +class Animal { +>Animal : Animal + + constructor(private species: string) { +>species : string + } + + printSpecies() { +>printSpecies : () => void + + let { species } = this; +>species : string +>this : this + + console.log(species); +>console.log(species) : void +>console.log : (msg: any) => void +>console : { log(msg: any): void; } +>log : (msg: any) => void +>species : string + } +} + + From e8c3d62d99023b8d1c2eb188bce29f5c7f00402e Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 3 Nov 2016 08:14:40 -0700 Subject: [PATCH 03/27] Lock tslint version to 4.0.0-dev.0, because 4.0.0-dev.1 complains about unnecessary semicolons following properties --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f943f89788..3bf9dbcff7b 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "travis-fold": "latest", "ts-node": "latest", "tsd": "latest", - "tslint": "next", + "tslint": "4.0.0-dev.0", "typescript": "next" }, "scripts": { From 83abd048b55f67e02e8fcbf69a9ed934056146bd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 3 Nov 2016 10:01:27 -0700 Subject: [PATCH 04/27] Correct assignability for keyof types and type parameters --- src/compiler/checker.ts | 21 +++++++++++++++++++++ src/compiler/types.ts | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 006b87cb542..b47f6264e3e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6825,6 +6825,27 @@ namespace ts { } } + if (target.flags & TypeFlags.TypeParameter) { + // Given a type parameter K with a constraint keyof T, a type S is + // assignable to K if S is assignable to keyof T. + let constraint = getConstraintOfTypeParameter(target); + if (constraint && constraint.flags & TypeFlags.Index) { + if (result = isRelatedTo(source, constraint, reportErrors)) { + return result; + } + } + } + else if (target.flags & TypeFlags.Index) { + // Given a type parameter T with a constraint C, a type S is assignable to + // keyof T if S is assignable to keyof C. + let constraint = getConstraintOfTypeParameter((target).type); + if (constraint) { + if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) { + return result; + } + } + } + if (source.flags & TypeFlags.TypeParameter) { let constraint = getConstraintOfTypeParameter(source); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e4c92c502a4..b865beca76b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2709,7 +2709,7 @@ namespace ts { EnumLike = Enum | EnumLiteral, UnionOrIntersection = Union | Intersection, StructuredType = Object | Union | Intersection, - StructuredOrTypeParameter = StructuredType | TypeParameter, + StructuredOrTypeParameter = StructuredType | TypeParameter | Index, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never From 4019265fe1bf8d7a0ef27fd1727304daff26c428 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 3 Nov 2016 10:01:42 -0700 Subject: [PATCH 05/27] Update tests --- .../types/keyof/keyofAndIndexedAccess.ts | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts index b63386a68a3..1e874aaf80f 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -7,6 +7,10 @@ class Shape { visible: boolean; } +class TaggedShape extends Shape { + tag: string; +} + class Item { name: string; price: number; @@ -149,6 +153,17 @@ function f32(key: K) { return shape[key]; // Shape[K] } +function f33(shape: S, key: K) { + let name = getProperty(shape, "name"); + let prop = getProperty(shape, key); + return prop; +} + +function f34(ts: TaggedShape) { + let tag1 = f33(ts, "tag"); + let tag2 = getProperty(ts, "tag"); +} + class C { public x: string; protected y: string; @@ -164,4 +179,36 @@ function f40(c: C) { let x: X = c["x"]; let y: Y = c["y"]; let z: Z = c["z"]; +} + +// Repros from #12011 + +class Base { + get(prop: K) { + return this[prop]; + } + set(prop: K, value: this[K]) { + this[prop] = value; + } +} + +class Person extends Base { + parts: number; + constructor(parts: number) { + super(); + this.set("parts", parts); + } + getParts() { + return this.get("parts") + } +} + +class OtherPerson { + parts: number; + constructor(parts: number) { + setProperty(this, "parts", parts); + } + getParts() { + return getProperty(this, "parts") + } } \ No newline at end of file From d9b0b637e3b014de2462dde173904d05d1720790 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 3 Nov 2016 10:01:53 -0700 Subject: [PATCH 06/27] Accept new baselines --- .../reference/keyofAndIndexedAccess.js | 120 +++ .../reference/keyofAndIndexedAccess.symbols | 718 +++++++++++------- .../reference/keyofAndIndexedAccess.types | 151 ++++ 3 files changed, 696 insertions(+), 293 deletions(-) diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js index 5d986f3e892..dd59a5a1b4c 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.js +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -7,6 +7,10 @@ class Shape { visible: boolean; } +class TaggedShape extends Shape { + tag: string; +} + class Item { name: string; price: number; @@ -149,6 +153,17 @@ function f32(key: K) { return shape[key]; // Shape[K] } +function f33(shape: S, key: K) { + let name = getProperty(shape, "name"); + let prop = getProperty(shape, key); + return prop; +} + +function f34(ts: TaggedShape) { + let tag1 = f33(ts, "tag"); + let tag2 = getProperty(ts, "tag"); +} + class C { public x: string; protected y: string; @@ -164,14 +179,58 @@ function f40(c: C) { let x: X = c["x"]; let y: Y = c["y"]; let z: Z = c["z"]; +} + +// Repros from #12011 + +class Base { + get(prop: K) { + return this[prop]; + } + set(prop: K, value: this[K]) { + this[prop] = value; + } +} + +class Person extends Base { + parts: number; + constructor(parts: number) { + super(); + this.set("parts", parts); + } + getParts() { + return this.get("parts") + } +} + +class OtherPerson { + parts: number; + constructor(parts: number) { + setProperty(this, "parts", parts); + } + getParts() { + return getProperty(this, "parts") + } } //// [keyofAndIndexedAccess.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; var Shape = (function () { function Shape() { } return Shape; }()); +var TaggedShape = (function (_super) { + __extends(TaggedShape, _super); + function TaggedShape() { + return _super.apply(this, arguments) || this; + } + return TaggedShape; +}(Shape)); var Item = (function () { function Item() { } @@ -249,6 +308,15 @@ function f32(key) { var shape = { name: "foo", width: 5, height: 10, visible: true }; return shape[key]; // Shape[K] } +function f33(shape, key) { + var name = getProperty(shape, "name"); + var prop = getProperty(shape, key); + return prop; +} +function f34(ts) { + var tag1 = f33(ts, "tag"); + var tag2 = getProperty(ts, "tag"); +} var C = (function () { function C() { } @@ -261,6 +329,39 @@ function f40(c) { var y = c["y"]; var z = c["z"]; } +// Repros from #12011 +var Base = (function () { + function Base() { + } + Base.prototype.get = function (prop) { + return this[prop]; + }; + Base.prototype.set = function (prop, value) { + this[prop] = value; + }; + return Base; +}()); +var Person = (function (_super) { + __extends(Person, _super); + function Person(parts) { + var _this = _super.call(this) || this; + _this.set("parts", parts); + return _this; + } + Person.prototype.getParts = function () { + return this.get("parts"); + }; + return Person; +}(Base)); +var OtherPerson = (function () { + function OtherPerson(parts) { + setProperty(this, "parts", parts); + } + OtherPerson.prototype.getParts = function () { + return getProperty(this, "parts"); + }; + return OtherPerson; +}()); //// [keyofAndIndexedAccess.d.ts] @@ -270,6 +371,9 @@ declare class Shape { height: number; visible: boolean; } +declare class TaggedShape extends Shape { + tag: string; +} declare class Item { name: string; price: number; @@ -342,9 +446,25 @@ declare function pluck(array: T[], key: K): T[K][]; declare function f30(shapes: Shape[]): void; declare function f31(key: K): Shape[K]; declare function f32(key: K): Shape[K]; +declare function f33(shape: S, key: K): S[K]; +declare function f34(ts: TaggedShape): void; declare class C { x: string; protected y: string; private z; } declare function f40(c: C): void; +declare class Base { + get(prop: K): this[K]; + set(prop: K, value: this[K]): void; +} +declare class Person extends Base { + parts: number; + constructor(parts: number); + getParts(): number; +} +declare class OtherPerson { + parts: number; + constructor(parts: number); + getParts(): number; +} diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index d3e967ed125..a76cf32b8d2 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -16,562 +16,694 @@ class Shape { >visible : Symbol(Shape.visible, Decl(keyofAndIndexedAccess.ts, 4, 19)) } +class TaggedShape extends Shape { +>TaggedShape : Symbol(TaggedShape, Decl(keyofAndIndexedAccess.ts, 6, 1)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + + tag: string; +>tag : Symbol(TaggedShape.tag, Decl(keyofAndIndexedAccess.ts, 8, 33)) +} + class Item { ->Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 6, 1)) +>Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 10, 1)) name: string; ->name : Symbol(Item.name, Decl(keyofAndIndexedAccess.ts, 8, 12)) +>name : Symbol(Item.name, Decl(keyofAndIndexedAccess.ts, 12, 12)) price: number; ->price : Symbol(Item.price, Decl(keyofAndIndexedAccess.ts, 9, 17)) +>price : Symbol(Item.price, Decl(keyofAndIndexedAccess.ts, 13, 17)) } class Options { ->Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 11, 1)) +>Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 15, 1)) visible: "yes" | "no"; ->visible : Symbol(Options.visible, Decl(keyofAndIndexedAccess.ts, 13, 15)) +>visible : Symbol(Options.visible, Decl(keyofAndIndexedAccess.ts, 17, 15)) } type Dictionary = { [x: string]: T }; ->Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 17, 16)) ->x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 17, 24)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 17, 16)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 19, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 21, 16)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 21, 24)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 21, 16)) const enum E { A, B, C } ->E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) ->A : Symbol(E.A, Decl(keyofAndIndexedAccess.ts, 19, 14)) ->B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 19, 17)) ->C : Symbol(E.C, Decl(keyofAndIndexedAccess.ts, 19, 20)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 21, 40)) +>A : Symbol(E.A, Decl(keyofAndIndexedAccess.ts, 23, 14)) +>B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 23, 17)) +>C : Symbol(E.C, Decl(keyofAndIndexedAccess.ts, 23, 20)) type K00 = keyof any; // string | number ->K00 : Symbol(K00, Decl(keyofAndIndexedAccess.ts, 19, 24)) +>K00 : Symbol(K00, Decl(keyofAndIndexedAccess.ts, 23, 24)) type K01 = keyof string; // number | "toString" | "charAt" | ... ->K01 : Symbol(K01, Decl(keyofAndIndexedAccess.ts, 21, 21)) +>K01 : Symbol(K01, Decl(keyofAndIndexedAccess.ts, 25, 21)) type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ... ->K02 : Symbol(K02, Decl(keyofAndIndexedAccess.ts, 22, 24)) +>K02 : Symbol(K02, Decl(keyofAndIndexedAccess.ts, 26, 24)) type K03 = keyof boolean; // "valueOf" ->K03 : Symbol(K03, Decl(keyofAndIndexedAccess.ts, 23, 24)) +>K03 : Symbol(K03, Decl(keyofAndIndexedAccess.ts, 27, 24)) type K04 = keyof void; // never ->K04 : Symbol(K04, Decl(keyofAndIndexedAccess.ts, 24, 25)) +>K04 : Symbol(K04, Decl(keyofAndIndexedAccess.ts, 28, 25)) type K05 = keyof undefined; // never ->K05 : Symbol(K05, Decl(keyofAndIndexedAccess.ts, 25, 22)) +>K05 : Symbol(K05, Decl(keyofAndIndexedAccess.ts, 29, 22)) type K06 = keyof null; // never ->K06 : Symbol(K06, Decl(keyofAndIndexedAccess.ts, 26, 27)) +>K06 : Symbol(K06, Decl(keyofAndIndexedAccess.ts, 30, 27)) type K07 = keyof never; // never ->K07 : Symbol(K07, Decl(keyofAndIndexedAccess.ts, 27, 22)) +>K07 : Symbol(K07, Decl(keyofAndIndexedAccess.ts, 31, 22)) type K10 = keyof Shape; // "name" | "width" | "height" | "visible" ->K10 : Symbol(K10, Decl(keyofAndIndexedAccess.ts, 28, 23)) +>K10 : Symbol(K10, Decl(keyofAndIndexedAccess.ts, 32, 23)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type K11 = keyof Shape[]; // number | "length" | "toString" | ... ->K11 : Symbol(K11, Decl(keyofAndIndexedAccess.ts, 30, 23)) +>K11 : Symbol(K11, Decl(keyofAndIndexedAccess.ts, 34, 23)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type K12 = keyof Dictionary; // string | number ->K12 : Symbol(K12, Decl(keyofAndIndexedAccess.ts, 31, 25)) ->Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>K12 : Symbol(K12, Decl(keyofAndIndexedAccess.ts, 35, 25)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 19, 1)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type K13 = keyof {}; // never ->K13 : Symbol(K13, Decl(keyofAndIndexedAccess.ts, 32, 35)) +>K13 : Symbol(K13, Decl(keyofAndIndexedAccess.ts, 36, 35)) type K14 = keyof Object; // "constructor" | "toString" | ... ->K14 : Symbol(K14, Decl(keyofAndIndexedAccess.ts, 33, 20)) +>K14 : Symbol(K14, Decl(keyofAndIndexedAccess.ts, 37, 20)) >Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ... ->K15 : Symbol(K15, Decl(keyofAndIndexedAccess.ts, 34, 24)) ->E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) +>K15 : Symbol(K15, Decl(keyofAndIndexedAccess.ts, 38, 24)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 21, 40)) type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ... ->K16 : Symbol(K16, Decl(keyofAndIndexedAccess.ts, 35, 19)) +>K16 : Symbol(K16, Decl(keyofAndIndexedAccess.ts, 39, 19)) type K17 = keyof (Shape | Item); // "name" ->K17 : Symbol(K17, Decl(keyofAndIndexedAccess.ts, 36, 34)) +>K17 : Symbol(K17, Decl(keyofAndIndexedAccess.ts, 40, 34)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 6, 1)) +>Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 10, 1)) type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price" ->K18 : Symbol(K18, Decl(keyofAndIndexedAccess.ts, 37, 32)) +>K18 : Symbol(K18, Decl(keyofAndIndexedAccess.ts, 41, 32)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 6, 1)) +>Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 10, 1)) type KeyOf = keyof T; ->KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 38, 32)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 40, 11)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 40, 11)) +>KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 42, 32)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 44, 11)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 44, 11)) type K20 = KeyOf; // "name" | "width" | "height" | "visible" ->K20 : Symbol(K20, Decl(keyofAndIndexedAccess.ts, 40, 24)) ->KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 38, 32)) +>K20 : Symbol(K20, Decl(keyofAndIndexedAccess.ts, 44, 24)) +>KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 42, 32)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type K21 = KeyOf>; // string | number ->K21 : Symbol(K21, Decl(keyofAndIndexedAccess.ts, 42, 24)) ->KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 38, 32)) ->Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>K21 : Symbol(K21, Decl(keyofAndIndexedAccess.ts, 46, 24)) +>KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 42, 32)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 19, 1)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type NAME = "name"; ->NAME : Symbol(NAME, Decl(keyofAndIndexedAccess.ts, 43, 36)) +>NAME : Symbol(NAME, Decl(keyofAndIndexedAccess.ts, 47, 36)) type WIDTH_OR_HEIGHT = "width" | "height"; ->WIDTH_OR_HEIGHT : Symbol(WIDTH_OR_HEIGHT, Decl(keyofAndIndexedAccess.ts, 45, 19)) +>WIDTH_OR_HEIGHT : Symbol(WIDTH_OR_HEIGHT, Decl(keyofAndIndexedAccess.ts, 49, 19)) type Q10 = Shape["name"]; // string ->Q10 : Symbol(Q10, Decl(keyofAndIndexedAccess.ts, 46, 42)) +>Q10 : Symbol(Q10, Decl(keyofAndIndexedAccess.ts, 50, 42)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type Q11 = Shape["width" | "height"]; // number ->Q11 : Symbol(Q11, Decl(keyofAndIndexedAccess.ts, 48, 25)) +>Q11 : Symbol(Q11, Decl(keyofAndIndexedAccess.ts, 52, 25)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type Q12 = Shape["name" | "visible"]; // string | boolean ->Q12 : Symbol(Q12, Decl(keyofAndIndexedAccess.ts, 49, 37)) +>Q12 : Symbol(Q12, Decl(keyofAndIndexedAccess.ts, 53, 37)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type Q20 = Shape[NAME]; // string ->Q20 : Symbol(Q20, Decl(keyofAndIndexedAccess.ts, 50, 37)) +>Q20 : Symbol(Q20, Decl(keyofAndIndexedAccess.ts, 54, 37)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->NAME : Symbol(NAME, Decl(keyofAndIndexedAccess.ts, 43, 36)) +>NAME : Symbol(NAME, Decl(keyofAndIndexedAccess.ts, 47, 36)) type Q21 = Shape[WIDTH_OR_HEIGHT]; // number ->Q21 : Symbol(Q21, Decl(keyofAndIndexedAccess.ts, 52, 23)) +>Q21 : Symbol(Q21, Decl(keyofAndIndexedAccess.ts, 56, 23)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->WIDTH_OR_HEIGHT : Symbol(WIDTH_OR_HEIGHT, Decl(keyofAndIndexedAccess.ts, 45, 19)) +>WIDTH_OR_HEIGHT : Symbol(WIDTH_OR_HEIGHT, Decl(keyofAndIndexedAccess.ts, 49, 19)) type Q30 = [string, number][0]; // string ->Q30 : Symbol(Q30, Decl(keyofAndIndexedAccess.ts, 53, 34)) +>Q30 : Symbol(Q30, Decl(keyofAndIndexedAccess.ts, 57, 34)) type Q31 = [string, number][1]; // number ->Q31 : Symbol(Q31, Decl(keyofAndIndexedAccess.ts, 55, 31)) +>Q31 : Symbol(Q31, Decl(keyofAndIndexedAccess.ts, 59, 31)) type Q32 = [string, number][2]; // string | number ->Q32 : Symbol(Q32, Decl(keyofAndIndexedAccess.ts, 56, 31)) +>Q32 : Symbol(Q32, Decl(keyofAndIndexedAccess.ts, 60, 31)) type Q33 = [string, number][E.A]; // string ->Q33 : Symbol(Q33, Decl(keyofAndIndexedAccess.ts, 57, 31)) ->E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) ->A : Symbol(E.A, Decl(keyofAndIndexedAccess.ts, 19, 14)) +>Q33 : Symbol(Q33, Decl(keyofAndIndexedAccess.ts, 61, 31)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 21, 40)) +>A : Symbol(E.A, Decl(keyofAndIndexedAccess.ts, 23, 14)) type Q34 = [string, number][E.B]; // number ->Q34 : Symbol(Q34, Decl(keyofAndIndexedAccess.ts, 58, 33)) ->E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) ->B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 19, 17)) +>Q34 : Symbol(Q34, Decl(keyofAndIndexedAccess.ts, 62, 33)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 21, 40)) +>B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 23, 17)) type Q35 = [string, number][E.C]; // string | number ->Q35 : Symbol(Q35, Decl(keyofAndIndexedAccess.ts, 59, 33)) ->E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) ->C : Symbol(E.C, Decl(keyofAndIndexedAccess.ts, 19, 20)) +>Q35 : Symbol(Q35, Decl(keyofAndIndexedAccess.ts, 63, 33)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 21, 40)) +>C : Symbol(E.C, Decl(keyofAndIndexedAccess.ts, 23, 20)) type Q36 = [string, number]["0"]; // string ->Q36 : Symbol(Q36, Decl(keyofAndIndexedAccess.ts, 60, 33)) +>Q36 : Symbol(Q36, Decl(keyofAndIndexedAccess.ts, 64, 33)) type Q37 = [string, number]["1"]; // string ->Q37 : Symbol(Q37, Decl(keyofAndIndexedAccess.ts, 61, 33)) +>Q37 : Symbol(Q37, Decl(keyofAndIndexedAccess.ts, 65, 33)) type Q40 = (Shape | Options)["visible"]; // boolean | "yes" | "no" ->Q40 : Symbol(Q40, Decl(keyofAndIndexedAccess.ts, 62, 33)) +>Q40 : Symbol(Q40, Decl(keyofAndIndexedAccess.ts, 66, 33)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 11, 1)) +>Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 15, 1)) type Q41 = (Shape & Options)["visible"]; // true & "yes" | true & "no" | false & "yes" | false & "no" ->Q41 : Symbol(Q41, Decl(keyofAndIndexedAccess.ts, 64, 40)) +>Q41 : Symbol(Q41, Decl(keyofAndIndexedAccess.ts, 68, 40)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 11, 1)) +>Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 15, 1)) type Q50 = Dictionary["howdy"]; // Shape ->Q50 : Symbol(Q50, Decl(keyofAndIndexedAccess.ts, 65, 40)) ->Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>Q50 : Symbol(Q50, Decl(keyofAndIndexedAccess.ts, 69, 40)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 19, 1)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type Q51 = Dictionary[123]; // Shape ->Q51 : Symbol(Q51, Decl(keyofAndIndexedAccess.ts, 67, 38)) ->Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>Q51 : Symbol(Q51, Decl(keyofAndIndexedAccess.ts, 71, 38)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 19, 1)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) type Q52 = Dictionary[E.B]; // Shape ->Q52 : Symbol(Q52, Decl(keyofAndIndexedAccess.ts, 68, 34)) ->Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>Q52 : Symbol(Q52, Decl(keyofAndIndexedAccess.ts, 72, 34)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 19, 1)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) ->B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 19, 17)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 21, 40)) +>B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 23, 17)) declare let cond: boolean; ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) function getProperty(obj: T, key: K) { ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 73, 21)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 73, 23)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 73, 21)) ->obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 73, 43)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 73, 21)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 73, 50)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 73, 23)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 77, 23)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 77, 43)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 77, 50)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 77, 23)) return obj[key]; ->obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 73, 43)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 73, 50)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 77, 43)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 77, 50)) } function setProperty(obj: T, key: K, value: T[K]) { ->setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 77, 23)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) ->obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 77, 43)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 77, 50)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 77, 23)) ->value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 77, 58)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 77, 23)) +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 79, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 81, 21)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 81, 23)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 81, 21)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 81, 43)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 81, 21)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 81, 50)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 81, 23)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 81, 58)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 81, 21)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 81, 23)) obj[key] = value; ->obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 77, 43)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 77, 50)) ->value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 77, 58)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 81, 43)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 81, 50)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 81, 58)) } function f10(shape: Shape) { ->f10 : Symbol(f10, Decl(keyofAndIndexedAccess.ts, 79, 1)) ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) +>f10 : Symbol(f10, Decl(keyofAndIndexedAccess.ts, 83, 1)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 85, 13)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) let name = getProperty(shape, "name"); // string ->name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 82, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 86, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 85, 13)) let widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number ->widthOrHeight : Symbol(widthOrHeight, Decl(keyofAndIndexedAccess.ts, 83, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>widthOrHeight : Symbol(widthOrHeight, Decl(keyofAndIndexedAccess.ts, 87, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 85, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) let nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean ->nameOrVisible : Symbol(nameOrVisible, Decl(keyofAndIndexedAccess.ts, 84, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>nameOrVisible : Symbol(nameOrVisible, Decl(keyofAndIndexedAccess.ts, 88, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 85, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) setProperty(shape, "name", "rectangle"); ->setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 79, 1)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 85, 13)) setProperty(shape, cond ? "width" : "height", 10); ->setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 79, 1)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 85, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) setProperty(shape, cond ? "name" : "visible", true); // Technically not safe ->setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 79, 1)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 85, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) } function f11(a: Shape[]) { ->f11 : Symbol(f11, Decl(keyofAndIndexedAccess.ts, 88, 1)) ->a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) +>f11 : Symbol(f11, Decl(keyofAndIndexedAccess.ts, 92, 1)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 94, 13)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) let len = getProperty(a, "length"); // number ->len : Symbol(len, Decl(keyofAndIndexedAccess.ts, 91, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) +>len : Symbol(len, Decl(keyofAndIndexedAccess.ts, 95, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 94, 13)) let shape = getProperty(a, 1000); // Shape ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 92, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 96, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 94, 13)) setProperty(a, 1000, getProperty(a, 1001)); ->setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) ->a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 79, 1)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 94, 13)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 94, 13)) } function f12(t: [Shape, boolean]) { ->f12 : Symbol(f12, Decl(keyofAndIndexedAccess.ts, 94, 1)) ->t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +>f12 : Symbol(f12, Decl(keyofAndIndexedAccess.ts, 98, 1)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 100, 13)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) let len = getProperty(t, "length"); ->len : Symbol(len, Decl(keyofAndIndexedAccess.ts, 97, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +>len : Symbol(len, Decl(keyofAndIndexedAccess.ts, 101, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 100, 13)) let s1 = getProperty(t, 0); // Shape ->s1 : Symbol(s1, Decl(keyofAndIndexedAccess.ts, 98, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +>s1 : Symbol(s1, Decl(keyofAndIndexedAccess.ts, 102, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 100, 13)) let s2 = getProperty(t, "0"); // Shape ->s2 : Symbol(s2, Decl(keyofAndIndexedAccess.ts, 99, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +>s2 : Symbol(s2, Decl(keyofAndIndexedAccess.ts, 103, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 100, 13)) let b1 = getProperty(t, 1); // boolean ->b1 : Symbol(b1, Decl(keyofAndIndexedAccess.ts, 100, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +>b1 : Symbol(b1, Decl(keyofAndIndexedAccess.ts, 104, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 100, 13)) let b2 = getProperty(t, "1"); // boolean ->b2 : Symbol(b2, Decl(keyofAndIndexedAccess.ts, 101, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +>b2 : Symbol(b2, Decl(keyofAndIndexedAccess.ts, 105, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 100, 13)) let x1 = getProperty(t, 2); // Shape | boolean ->x1 : Symbol(x1, Decl(keyofAndIndexedAccess.ts, 102, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +>x1 : Symbol(x1, Decl(keyofAndIndexedAccess.ts, 106, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 100, 13)) } function f13(foo: any, bar: any) { ->f13 : Symbol(f13, Decl(keyofAndIndexedAccess.ts, 103, 1)) ->foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 105, 13)) ->bar : Symbol(bar, Decl(keyofAndIndexedAccess.ts, 105, 22)) +>f13 : Symbol(f13, Decl(keyofAndIndexedAccess.ts, 107, 1)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 109, 13)) +>bar : Symbol(bar, Decl(keyofAndIndexedAccess.ts, 109, 22)) let x = getProperty(foo, "x"); // any ->x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 106, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 105, 13)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 110, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 109, 13)) let y = getProperty(foo, 100); // any ->y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 107, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 105, 13)) +>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 111, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 109, 13)) let z = getProperty(foo, bar); // any ->z : Symbol(z, Decl(keyofAndIndexedAccess.ts, 108, 7)) ->getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) ->foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 105, 13)) ->bar : Symbol(bar, Decl(keyofAndIndexedAccess.ts, 105, 22)) +>z : Symbol(z, Decl(keyofAndIndexedAccess.ts, 112, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 109, 13)) +>bar : Symbol(bar, Decl(keyofAndIndexedAccess.ts, 109, 22)) } class Component { ->Component : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 109, 1)) ->PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) +>Component : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 113, 1)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 115, 16)) props: PropType; ->props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) ->PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) +>props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 115, 27)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 115, 16)) getProperty(key: K) { ->getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 113, 16)) ->PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 113, 42)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 113, 16)) +>getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 116, 20)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 117, 16)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 115, 16)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 117, 42)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 117, 16)) return this.props[key]; ->this.props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) ->this : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 109, 1)) ->props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 113, 42)) +>this.props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 115, 27)) +>this : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 113, 1)) +>props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 115, 27)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 117, 42)) } setProperty(key: K, value: PropType[K]) { ->setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 116, 16)) ->PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 116, 42)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 116, 16)) ->value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 116, 49)) ->PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 116, 16)) +>setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 119, 5)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 120, 16)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 115, 16)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 120, 42)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 120, 16)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 120, 49)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 115, 16)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 120, 16)) this.props[key] = value; ->this.props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) ->this : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 109, 1)) ->props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 116, 42)) ->value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 116, 49)) +>this.props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 115, 27)) +>this : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 113, 1)) +>props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 115, 27)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 120, 42)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 120, 49)) } } function f20(component: Component) { ->f20 : Symbol(f20, Decl(keyofAndIndexedAccess.ts, 119, 1)) ->component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) ->Component : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 109, 1)) +>f20 : Symbol(f20, Decl(keyofAndIndexedAccess.ts, 123, 1)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 125, 13)) +>Component : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 113, 1)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) let name = component.getProperty("name"); // string ->name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 122, 7)) ->component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) ->component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) ->getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 126, 7)) +>component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 116, 20)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 125, 13)) +>getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 116, 20)) let widthOrHeight = component.getProperty(cond ? "width" : "height"); // number ->widthOrHeight : Symbol(widthOrHeight, Decl(keyofAndIndexedAccess.ts, 123, 7)) ->component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) ->component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) ->getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>widthOrHeight : Symbol(widthOrHeight, Decl(keyofAndIndexedAccess.ts, 127, 7)) +>component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 116, 20)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 125, 13)) +>getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 116, 20)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) let nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean ->nameOrVisible : Symbol(nameOrVisible, Decl(keyofAndIndexedAccess.ts, 124, 7)) ->component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) ->component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) ->getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>nameOrVisible : Symbol(nameOrVisible, Decl(keyofAndIndexedAccess.ts, 128, 7)) +>component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 116, 20)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 125, 13)) +>getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 116, 20)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) component.setProperty("name", "rectangle"); ->component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) ->component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) ->setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) +>component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 119, 5)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 125, 13)) +>setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 119, 5)) component.setProperty(cond ? "width" : "height", 10) ->component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) ->component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) ->setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 119, 5)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 125, 13)) +>setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 119, 5)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) component.setProperty(cond ? "name" : "visible", true); // Technically not safe ->component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) ->component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) ->setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 119, 5)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 125, 13)) +>setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 119, 5)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) } function pluck(array: T[], key: K) { ->pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 128, 1)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 130, 15)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 130, 17)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 130, 15)) ->array : Symbol(array, Decl(keyofAndIndexedAccess.ts, 130, 37)) ->T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 130, 15)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 130, 48)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 130, 17)) +>pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 132, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 134, 15)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 134, 17)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 134, 15)) +>array : Symbol(array, Decl(keyofAndIndexedAccess.ts, 134, 37)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 134, 15)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 134, 48)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 134, 17)) return array.map(x => x[key]); >array.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->array : Symbol(array, Decl(keyofAndIndexedAccess.ts, 130, 37)) +>array : Symbol(array, Decl(keyofAndIndexedAccess.ts, 134, 37)) >map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 131, 21)) ->x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 131, 21)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 130, 48)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 135, 21)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 135, 21)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 134, 48)) } function f30(shapes: Shape[]) { ->f30 : Symbol(f30, Decl(keyofAndIndexedAccess.ts, 132, 1)) ->shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 134, 13)) +>f30 : Symbol(f30, Decl(keyofAndIndexedAccess.ts, 136, 1)) +>shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 138, 13)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) let names = pluck(shapes, "name"); // string[] ->names : Symbol(names, Decl(keyofAndIndexedAccess.ts, 135, 7)) ->pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 128, 1)) ->shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 134, 13)) +>names : Symbol(names, Decl(keyofAndIndexedAccess.ts, 139, 7)) +>pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 132, 1)) +>shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 138, 13)) let widths = pluck(shapes, "width"); // number[] ->widths : Symbol(widths, Decl(keyofAndIndexedAccess.ts, 136, 7)) ->pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 128, 1)) ->shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 134, 13)) +>widths : Symbol(widths, Decl(keyofAndIndexedAccess.ts, 140, 7)) +>pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 132, 1)) +>shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 138, 13)) let nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[] ->nameOrVisibles : Symbol(nameOrVisibles, Decl(keyofAndIndexedAccess.ts, 137, 7)) ->pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 128, 1)) ->shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 134, 13)) ->cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +>nameOrVisibles : Symbol(nameOrVisibles, Decl(keyofAndIndexedAccess.ts, 141, 7)) +>pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 132, 1)) +>shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 138, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 75, 11)) } function f31(key: K) { ->f31 : Symbol(f31, Decl(keyofAndIndexedAccess.ts, 138, 1)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 140, 13)) +>f31 : Symbol(f31, Decl(keyofAndIndexedAccess.ts, 142, 1)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 144, 13)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 140, 36)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 140, 13)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 144, 36)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 144, 13)) const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 141, 9)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 145, 9)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 141, 26)) ->width : Symbol(width, Decl(keyofAndIndexedAccess.ts, 141, 39)) ->height : Symbol(height, Decl(keyofAndIndexedAccess.ts, 141, 49)) ->visible : Symbol(visible, Decl(keyofAndIndexedAccess.ts, 141, 61)) +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 145, 26)) +>width : Symbol(width, Decl(keyofAndIndexedAccess.ts, 145, 39)) +>height : Symbol(height, Decl(keyofAndIndexedAccess.ts, 145, 49)) +>visible : Symbol(visible, Decl(keyofAndIndexedAccess.ts, 145, 61)) return shape[key]; // Shape[K] ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 141, 9)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 140, 36)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 145, 9)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 144, 36)) } function f32(key: K) { ->f32 : Symbol(f32, Decl(keyofAndIndexedAccess.ts, 143, 1)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 145, 13)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 145, 43)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 145, 13)) +>f32 : Symbol(f32, Decl(keyofAndIndexedAccess.ts, 147, 1)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 149, 13)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 149, 43)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 149, 13)) const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 146, 9)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 150, 9)) >Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) ->name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 146, 26)) ->width : Symbol(width, Decl(keyofAndIndexedAccess.ts, 146, 39)) ->height : Symbol(height, Decl(keyofAndIndexedAccess.ts, 146, 49)) ->visible : Symbol(visible, Decl(keyofAndIndexedAccess.ts, 146, 61)) +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 150, 26)) +>width : Symbol(width, Decl(keyofAndIndexedAccess.ts, 150, 39)) +>height : Symbol(height, Decl(keyofAndIndexedAccess.ts, 150, 49)) +>visible : Symbol(visible, Decl(keyofAndIndexedAccess.ts, 150, 61)) return shape[key]; // Shape[K] ->shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 146, 9)) ->key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 145, 43)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 150, 9)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 149, 43)) +} + +function f33(shape: S, key: K) { +>f33 : Symbol(f33, Decl(keyofAndIndexedAccess.ts, 152, 1)) +>S : Symbol(S, Decl(keyofAndIndexedAccess.ts, 154, 13)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 154, 29)) +>S : Symbol(S, Decl(keyofAndIndexedAccess.ts, 154, 13)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 154, 49)) +>S : Symbol(S, Decl(keyofAndIndexedAccess.ts, 154, 13)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 154, 58)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 154, 29)) + + let name = getProperty(shape, "name"); +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 155, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 154, 49)) + + let prop = getProperty(shape, key); +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 156, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 154, 49)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 154, 58)) + + return prop; +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 156, 7)) +} + +function f34(ts: TaggedShape) { +>f34 : Symbol(f34, Decl(keyofAndIndexedAccess.ts, 158, 1)) +>ts : Symbol(ts, Decl(keyofAndIndexedAccess.ts, 160, 13)) +>TaggedShape : Symbol(TaggedShape, Decl(keyofAndIndexedAccess.ts, 6, 1)) + + let tag1 = f33(ts, "tag"); +>tag1 : Symbol(tag1, Decl(keyofAndIndexedAccess.ts, 161, 7)) +>f33 : Symbol(f33, Decl(keyofAndIndexedAccess.ts, 152, 1)) +>ts : Symbol(ts, Decl(keyofAndIndexedAccess.ts, 160, 13)) + + let tag2 = getProperty(ts, "tag"); +>tag2 : Symbol(tag2, Decl(keyofAndIndexedAccess.ts, 162, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>ts : Symbol(ts, Decl(keyofAndIndexedAccess.ts, 160, 13)) } class C { ->C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 163, 1)) public x: string; ->x : Symbol(C.x, Decl(keyofAndIndexedAccess.ts, 150, 9)) +>x : Symbol(C.x, Decl(keyofAndIndexedAccess.ts, 165, 9)) protected y: string; ->y : Symbol(C.y, Decl(keyofAndIndexedAccess.ts, 151, 21)) +>y : Symbol(C.y, Decl(keyofAndIndexedAccess.ts, 166, 21)) private z: string; ->z : Symbol(C.z, Decl(keyofAndIndexedAccess.ts, 152, 24)) +>z : Symbol(C.z, Decl(keyofAndIndexedAccess.ts, 167, 24)) } // Indexed access expressions have always permitted access to private and protected members. // For consistency we also permit such access in indexed access types. function f40(c: C) { ->f40 : Symbol(f40, Decl(keyofAndIndexedAccess.ts, 154, 1)) ->c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 158, 13)) ->C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) +>f40 : Symbol(f40, Decl(keyofAndIndexedAccess.ts, 169, 1)) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 173, 13)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 163, 1)) type X = C["x"]; ->X : Symbol(X, Decl(keyofAndIndexedAccess.ts, 158, 20)) ->C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) +>X : Symbol(X, Decl(keyofAndIndexedAccess.ts, 173, 20)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 163, 1)) type Y = C["y"]; ->Y : Symbol(Y, Decl(keyofAndIndexedAccess.ts, 159, 20)) ->C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) +>Y : Symbol(Y, Decl(keyofAndIndexedAccess.ts, 174, 20)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 163, 1)) type Z = C["z"]; ->Z : Symbol(Z, Decl(keyofAndIndexedAccess.ts, 160, 20)) ->C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) +>Z : Symbol(Z, Decl(keyofAndIndexedAccess.ts, 175, 20)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 163, 1)) let x: X = c["x"]; ->x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 162, 7)) ->X : Symbol(X, Decl(keyofAndIndexedAccess.ts, 158, 20)) ->c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 158, 13)) ->"x" : Symbol(C.x, Decl(keyofAndIndexedAccess.ts, 150, 9)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 177, 7)) +>X : Symbol(X, Decl(keyofAndIndexedAccess.ts, 173, 20)) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 173, 13)) +>"x" : Symbol(C.x, Decl(keyofAndIndexedAccess.ts, 165, 9)) let y: Y = c["y"]; ->y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 163, 7)) ->Y : Symbol(Y, Decl(keyofAndIndexedAccess.ts, 159, 20)) ->c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 158, 13)) ->"y" : Symbol(C.y, Decl(keyofAndIndexedAccess.ts, 151, 21)) +>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 178, 7)) +>Y : Symbol(Y, Decl(keyofAndIndexedAccess.ts, 174, 20)) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 173, 13)) +>"y" : Symbol(C.y, Decl(keyofAndIndexedAccess.ts, 166, 21)) let z: Z = c["z"]; ->z : Symbol(z, Decl(keyofAndIndexedAccess.ts, 164, 7)) ->Z : Symbol(Z, Decl(keyofAndIndexedAccess.ts, 160, 20)) ->c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 158, 13)) ->"z" : Symbol(C.z, Decl(keyofAndIndexedAccess.ts, 152, 24)) +>z : Symbol(z, Decl(keyofAndIndexedAccess.ts, 179, 7)) +>Z : Symbol(Z, Decl(keyofAndIndexedAccess.ts, 175, 20)) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 173, 13)) +>"z" : Symbol(C.z, Decl(keyofAndIndexedAccess.ts, 167, 24)) +} + +// Repros from #12011 + +class Base { +>Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) + + get(prop: K) { +>get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 184, 12)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 185, 8)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 185, 30)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 185, 8)) + + return this[prop]; +>this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 185, 30)) + } + set(prop: K, value: this[K]) { +>set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 187, 5)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 188, 8)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 188, 30)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 188, 8)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 188, 38)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 188, 8)) + + this[prop] = value; +>this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 188, 30)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 188, 38)) + } +} + +class Person extends Base { +>Person : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 191, 1)) +>Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) + + parts: number; +>parts : Symbol(Person.parts, Decl(keyofAndIndexedAccess.ts, 193, 27)) + + constructor(parts: number) { +>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 195, 16)) + + super(); +>super : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) + + this.set("parts", parts); +>this.set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 187, 5)) +>this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 191, 1)) +>set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 187, 5)) +>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 195, 16)) + } + getParts() { +>getParts : Symbol(Person.getParts, Decl(keyofAndIndexedAccess.ts, 198, 5)) + + return this.get("parts") +>this.get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 184, 12)) +>this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 191, 1)) +>get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 184, 12)) + } +} + +class OtherPerson { +>OtherPerson : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 202, 1)) + + parts: number; +>parts : Symbol(OtherPerson.parts, Decl(keyofAndIndexedAccess.ts, 204, 19)) + + constructor(parts: number) { +>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 206, 16)) + + setProperty(this, "parts", parts); +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 79, 1)) +>this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 202, 1)) +>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 206, 16)) + } + getParts() { +>getParts : Symbol(OtherPerson.getParts, Decl(keyofAndIndexedAccess.ts, 208, 5)) + + return getProperty(this, "parts") +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) +>this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 202, 1)) + } } diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index 74c06a2535d..a5395db8292 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -16,6 +16,14 @@ class Shape { >visible : boolean } +class TaggedShape extends Shape { +>TaggedShape : TaggedShape +>Shape : Shape + + tag: string; +>tag : string +} + class Item { >Item : Item @@ -626,6 +634,55 @@ function f32(key: K) { >key : K } +function f33(shape: S, key: K) { +>f33 : (shape: S, key: K) => S[K] +>S : S +>Shape : Shape +>K : K +>S : S +>shape : S +>S : S +>key : K +>K : K + + let name = getProperty(shape, "name"); +>name : string +>getProperty(shape, "name") : string +>getProperty : (obj: T, key: K) => T[K] +>shape : S +>"name" : "name" + + let prop = getProperty(shape, key); +>prop : S[K] +>getProperty(shape, key) : S[K] +>getProperty : (obj: T, key: K) => T[K] +>shape : S +>key : K + + return prop; +>prop : S[K] +} + +function f34(ts: TaggedShape) { +>f34 : (ts: TaggedShape) => void +>ts : TaggedShape +>TaggedShape : TaggedShape + + let tag1 = f33(ts, "tag"); +>tag1 : string +>f33(ts, "tag") : string +>f33 : (shape: S, key: K) => S[K] +>ts : TaggedShape +>"tag" : "tag" + + let tag2 = getProperty(ts, "tag"); +>tag2 : string +>getProperty(ts, "tag") : string +>getProperty : (obj: T, key: K) => T[K] +>ts : TaggedShape +>"tag" : "tag" +} + class C { >C : C @@ -679,3 +736,97 @@ function f40(c: C) { >c : C >"z" : "z" } + +// Repros from #12011 + +class Base { +>Base : Base + + get(prop: K) { +>get : (prop: K) => this[K] +>K : K +>prop : K +>K : K + + return this[prop]; +>this[prop] : this[K] +>this : this +>prop : K + } + set(prop: K, value: this[K]) { +>set : (prop: K, value: this[K]) => void +>K : K +>prop : K +>K : K +>value : this[K] +>K : K + + this[prop] = value; +>this[prop] = value : this[K] +>this[prop] : this[K] +>this : this +>prop : K +>value : this[K] + } +} + +class Person extends Base { +>Person : Person +>Base : Base + + parts: number; +>parts : number + + constructor(parts: number) { +>parts : number + + super(); +>super() : void +>super : typeof Base + + this.set("parts", parts); +>this.set("parts", parts) : void +>this.set : (prop: K, value: this[K]) => void +>this : this +>set : (prop: K, value: this[K]) => void +>"parts" : "parts" +>parts : number + } + getParts() { +>getParts : () => number + + return this.get("parts") +>this.get("parts") : number +>this.get : (prop: K) => this[K] +>this : this +>get : (prop: K) => this[K] +>"parts" : "parts" + } +} + +class OtherPerson { +>OtherPerson : OtherPerson + + parts: number; +>parts : number + + constructor(parts: number) { +>parts : number + + setProperty(this, "parts", parts); +>setProperty(this, "parts", parts) : void +>setProperty : (obj: T, key: K, value: T[K]) => void +>this : this +>"parts" : "parts" +>parts : number + } + getParts() { +>getParts : () => number + + return getProperty(this, "parts") +>getProperty(this, "parts") : number +>getProperty : (obj: T, key: K) => T[K] +>this : this +>"parts" : "parts" + } +} From 6a5de5d00ee092322a1cb6d68809c37366090ee4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 3 Nov 2016 10:55:58 -0700 Subject: [PATCH 07/27] Fix linting errors --- 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 b47f6264e3e..28b14502af9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6828,7 +6828,7 @@ namespace ts { if (target.flags & TypeFlags.TypeParameter) { // Given a type parameter K with a constraint keyof T, a type S is // assignable to K if S is assignable to keyof T. - let constraint = getConstraintOfTypeParameter(target); + const constraint = getConstraintOfTypeParameter(target); if (constraint && constraint.flags & TypeFlags.Index) { if (result = isRelatedTo(source, constraint, reportErrors)) { return result; @@ -6838,7 +6838,7 @@ namespace ts { else if (target.flags & TypeFlags.Index) { // Given a type parameter T with a constraint C, a type S is assignable to // keyof T if S is assignable to keyof C. - let constraint = getConstraintOfTypeParameter((target).type); + const constraint = getConstraintOfTypeParameter((target).type); if (constraint) { if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) { return result; From cbec19afd76855b48c95ba09498ac21d5a17b544 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 3 Nov 2016 17:21:36 -0700 Subject: [PATCH 08/27] Ensure transformFlags are correct before visiting a node. --- src/compiler/visitor.ts | 2 + tests/baselines/reference/callWithSpread.js | 24 ++- .../reference/callWithSpread.symbols | 115 +++++++++--- .../baselines/reference/callWithSpread.types | 177 ++++++++++++++---- .../functionCalls/callWithSpread.ts | 10 +- 5 files changed, 257 insertions(+), 71 deletions(-) diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 609031a8221..45b82a6a08a 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -553,6 +553,7 @@ namespace ts { return undefined; } + aggregateTransformFlags(node); const visited = visitor(node); if (visited === node) { return node; @@ -621,6 +622,7 @@ namespace ts { // Visit each original node. for (let i = 0; i < count; i++) { const node = nodes[i + start]; + aggregateTransformFlags(node); const visited = node !== undefined ? visitor(node) : undefined; if (updated !== undefined || visited === undefined || visited !== node) { if (updated === undefined) { diff --git a/tests/baselines/reference/callWithSpread.js b/tests/baselines/reference/callWithSpread.js index 161eb36dbcf..69f7e4e30b0 100644 --- a/tests/baselines/reference/callWithSpread.js +++ b/tests/baselines/reference/callWithSpread.js @@ -1,6 +1,6 @@ //// [callWithSpread.ts] interface X { - foo(x: number, y: number, ...z: string[]); + foo(x: number, y: number, ...z: string[]): X; } function foo(x: number, y: number, ...z: string[]) { @@ -19,10 +19,18 @@ obj.foo(1, 2, "abc"); obj.foo(1, 2, ...a); obj.foo(1, 2, ...a, "abc"); +obj.foo(1, 2, ...a).foo(1, 2, "abc"); +obj.foo(1, 2, ...a).foo(1, 2, ...a); +obj.foo(1, 2, ...a).foo(1, 2, ...a, "abc"); + (obj.foo)(1, 2, "abc"); (obj.foo)(1, 2, ...a); (obj.foo)(1, 2, ...a, "abc"); +((obj.foo)(1, 2, ...a).foo)(1, 2, "abc"); +((obj.foo)(1, 2, ...a).foo)(1, 2, ...a); +((obj.foo)(1, 2, ...a).foo)(1, 2, ...a, "abc"); + xa[1].foo(1, 2, "abc"); xa[1].foo(1, 2, ...a); xa[1].foo(1, 2, ...a, "abc"); @@ -72,13 +80,19 @@ foo.apply(void 0, [1, 2].concat(a, ["abc"])); obj.foo(1, 2, "abc"); obj.foo.apply(obj, [1, 2].concat(a)); obj.foo.apply(obj, [1, 2].concat(a, ["abc"])); +obj.foo.apply(obj, [1, 2].concat(a)).foo(1, 2, "abc"); +(_a = obj.foo.apply(obj, [1, 2].concat(a))).foo.apply(_a, [1, 2].concat(a)); +(_b = obj.foo.apply(obj, [1, 2].concat(a))).foo.apply(_b, [1, 2].concat(a, ["abc"])); (obj.foo)(1, 2, "abc"); obj.foo.apply(obj, [1, 2].concat(a)); obj.foo.apply(obj, [1, 2].concat(a, ["abc"])); +(obj.foo.apply(obj, [1, 2].concat(a)).foo)(1, 2, "abc"); +(_c = obj.foo.apply(obj, [1, 2].concat(a))).foo.apply(_c, [1, 2].concat(a)); +(_d = obj.foo.apply(obj, [1, 2].concat(a))).foo.apply(_d, [1, 2].concat(a, ["abc"])); xa[1].foo(1, 2, "abc"); -(_a = xa[1]).foo.apply(_a, [1, 2].concat(a)); -(_b = xa[1]).foo.apply(_b, [1, 2].concat(a, ["abc"])); -(_c = xa[1]).foo.apply(_c, [1, 2, "abc"]); +(_e = xa[1]).foo.apply(_e, [1, 2].concat(a)); +(_f = xa[1]).foo.apply(_f, [1, 2].concat(a, ["abc"])); +(_g = xa[1]).foo.apply(_g, [1, 2, "abc"]); var C = (function () { function C(x, y) { var z = []; @@ -109,4 +123,4 @@ var D = (function (_super) { }; return D; }(C)); -var _a, _b, _c; +var _a, _b, _c, _d, _e, _f, _g; diff --git a/tests/baselines/reference/callWithSpread.symbols b/tests/baselines/reference/callWithSpread.symbols index bc2d9bfebd9..42331422df7 100644 --- a/tests/baselines/reference/callWithSpread.symbols +++ b/tests/baselines/reference/callWithSpread.symbols @@ -2,11 +2,12 @@ interface X { >X : Symbol(X, Decl(callWithSpread.ts, 0, 0)) - foo(x: number, y: number, ...z: string[]); + foo(x: number, y: number, ...z: string[]): X; >foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) >x : Symbol(x, Decl(callWithSpread.ts, 1, 8)) >y : Symbol(y, Decl(callWithSpread.ts, 1, 18)) >z : Symbol(z, Decl(callWithSpread.ts, 1, 29)) +>X : Symbol(X, Decl(callWithSpread.ts, 0, 0)) } function foo(x: number, y: number, ...z: string[]) { @@ -58,6 +59,32 @@ obj.foo(1, 2, ...a, "abc"); >foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) >a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) +obj.foo(1, 2, ...a).foo(1, 2, "abc"); +>obj.foo(1, 2, ...a).foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj.foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj : Symbol(obj, Decl(callWithSpread.ts, 9, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) + +obj.foo(1, 2, ...a).foo(1, 2, ...a); +>obj.foo(1, 2, ...a).foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj.foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj : Symbol(obj, Decl(callWithSpread.ts, 9, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) + +obj.foo(1, 2, ...a).foo(1, 2, ...a, "abc"); +>obj.foo(1, 2, ...a).foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj.foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj : Symbol(obj, Decl(callWithSpread.ts, 9, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) + (obj.foo)(1, 2, "abc"); >obj.foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) >obj : Symbol(obj, Decl(callWithSpread.ts, 9, 3)) @@ -75,6 +102,32 @@ obj.foo(1, 2, ...a, "abc"); >foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) >a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) +((obj.foo)(1, 2, ...a).foo)(1, 2, "abc"); +>(obj.foo)(1, 2, ...a).foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj.foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj : Symbol(obj, Decl(callWithSpread.ts, 9, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) + +((obj.foo)(1, 2, ...a).foo)(1, 2, ...a); +>(obj.foo)(1, 2, ...a).foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj.foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj : Symbol(obj, Decl(callWithSpread.ts, 9, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) + +((obj.foo)(1, 2, ...a).foo)(1, 2, ...a, "abc"); +>(obj.foo)(1, 2, ...a).foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj.foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>obj : Symbol(obj, Decl(callWithSpread.ts, 9, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) +>foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) +>a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) + xa[1].foo(1, 2, "abc"); >xa[1].foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) >xa : Symbol(xa, Decl(callWithSpread.ts, 10, 3)) @@ -99,60 +152,60 @@ xa[1].foo(1, 2, ...a, "abc"); >foo : Symbol(X.foo, Decl(callWithSpread.ts, 0, 13)) class C { ->C : Symbol(C, Decl(callWithSpread.ts, 28, 40)) +>C : Symbol(C, Decl(callWithSpread.ts, 36, 40)) constructor(x: number, y: number, ...z: string[]) { ->x : Symbol(x, Decl(callWithSpread.ts, 31, 16)) ->y : Symbol(y, Decl(callWithSpread.ts, 31, 26)) ->z : Symbol(z, Decl(callWithSpread.ts, 31, 37)) +>x : Symbol(x, Decl(callWithSpread.ts, 39, 16)) +>y : Symbol(y, Decl(callWithSpread.ts, 39, 26)) +>z : Symbol(z, Decl(callWithSpread.ts, 39, 37)) this.foo(x, y); ->this.foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) ->this : Symbol(C, Decl(callWithSpread.ts, 28, 40)) ->foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) ->x : Symbol(x, Decl(callWithSpread.ts, 31, 16)) ->y : Symbol(y, Decl(callWithSpread.ts, 31, 26)) +>this.foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) +>this : Symbol(C, Decl(callWithSpread.ts, 36, 40)) +>foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) +>x : Symbol(x, Decl(callWithSpread.ts, 39, 16)) +>y : Symbol(y, Decl(callWithSpread.ts, 39, 26)) this.foo(x, y, ...z); ->this.foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) ->this : Symbol(C, Decl(callWithSpread.ts, 28, 40)) ->foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) ->x : Symbol(x, Decl(callWithSpread.ts, 31, 16)) ->y : Symbol(y, Decl(callWithSpread.ts, 31, 26)) ->z : Symbol(z, Decl(callWithSpread.ts, 31, 37)) +>this.foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) +>this : Symbol(C, Decl(callWithSpread.ts, 36, 40)) +>foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) +>x : Symbol(x, Decl(callWithSpread.ts, 39, 16)) +>y : Symbol(y, Decl(callWithSpread.ts, 39, 26)) +>z : Symbol(z, Decl(callWithSpread.ts, 39, 37)) } foo(x: number, y: number, ...z: string[]) { ->foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) ->x : Symbol(x, Decl(callWithSpread.ts, 35, 8)) ->y : Symbol(y, Decl(callWithSpread.ts, 35, 18)) ->z : Symbol(z, Decl(callWithSpread.ts, 35, 29)) +>foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) +>x : Symbol(x, Decl(callWithSpread.ts, 43, 8)) +>y : Symbol(y, Decl(callWithSpread.ts, 43, 18)) +>z : Symbol(z, Decl(callWithSpread.ts, 43, 29)) } } class D extends C { ->D : Symbol(D, Decl(callWithSpread.ts, 37, 1)) ->C : Symbol(C, Decl(callWithSpread.ts, 28, 40)) +>D : Symbol(D, Decl(callWithSpread.ts, 45, 1)) +>C : Symbol(C, Decl(callWithSpread.ts, 36, 40)) constructor() { super(1, 2); ->super : Symbol(C, Decl(callWithSpread.ts, 28, 40)) +>super : Symbol(C, Decl(callWithSpread.ts, 36, 40)) super(1, 2, ...a); ->super : Symbol(C, Decl(callWithSpread.ts, 28, 40)) +>super : Symbol(C, Decl(callWithSpread.ts, 36, 40)) >a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) } foo() { ->foo : Symbol(D.foo, Decl(callWithSpread.ts, 43, 5)) +>foo : Symbol(D.foo, Decl(callWithSpread.ts, 51, 5)) super.foo(1, 2); ->super.foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) ->super : Symbol(C, Decl(callWithSpread.ts, 28, 40)) ->foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) +>super.foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) +>super : Symbol(C, Decl(callWithSpread.ts, 36, 40)) +>foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) super.foo(1, 2, ...a); ->super.foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) ->super : Symbol(C, Decl(callWithSpread.ts, 28, 40)) ->foo : Symbol(C.foo, Decl(callWithSpread.ts, 34, 5)) +>super.foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) +>super : Symbol(C, Decl(callWithSpread.ts, 36, 40)) +>foo : Symbol(C.foo, Decl(callWithSpread.ts, 42, 5)) >a : Symbol(a, Decl(callWithSpread.ts, 7, 3)) } } diff --git a/tests/baselines/reference/callWithSpread.types b/tests/baselines/reference/callWithSpread.types index c9403f1bb69..5af9d2fef84 100644 --- a/tests/baselines/reference/callWithSpread.types +++ b/tests/baselines/reference/callWithSpread.types @@ -2,11 +2,12 @@ interface X { >X : X - foo(x: number, y: number, ...z: string[]); ->foo : (x: number, y: number, ...z: string[]) => any + foo(x: number, y: number, ...z: string[]): X; +>foo : (x: number, y: number, ...z: string[]) => X >x : number >y : number >z : string[] +>X : X } function foo(x: number, y: number, ...z: string[]) { @@ -55,29 +56,80 @@ foo(1, 2, ...a, "abc"); >"abc" : "abc" obj.foo(1, 2, "abc"); ->obj.foo(1, 2, "abc") : any ->obj.foo : (x: number, y: number, ...z: string[]) => any +>obj.foo(1, 2, "abc") : X +>obj.foo : (x: number, y: number, ...z: string[]) => X >obj : X ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >"abc" : "abc" obj.foo(1, 2, ...a); ->obj.foo(1, 2, ...a) : any ->obj.foo : (x: number, y: number, ...z: string[]) => any +>obj.foo(1, 2, ...a) : X +>obj.foo : (x: number, y: number, ...z: string[]) => X >obj : X ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >...a : string >a : string[] obj.foo(1, 2, ...a, "abc"); ->obj.foo(1, 2, ...a, "abc") : any ->obj.foo : (x: number, y: number, ...z: string[]) => any +>obj.foo(1, 2, ...a, "abc") : X +>obj.foo : (x: number, y: number, ...z: string[]) => X >obj : X ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] +>"abc" : "abc" + +obj.foo(1, 2, ...a).foo(1, 2, "abc"); +>obj.foo(1, 2, ...a).foo(1, 2, "abc") : X +>obj.foo(1, 2, ...a).foo : (x: number, y: number, ...z: string[]) => X +>obj.foo(1, 2, ...a) : X +>obj.foo : (x: number, y: number, ...z: string[]) => X +>obj : X +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>"abc" : "abc" + +obj.foo(1, 2, ...a).foo(1, 2, ...a); +>obj.foo(1, 2, ...a).foo(1, 2, ...a) : X +>obj.foo(1, 2, ...a).foo : (x: number, y: number, ...z: string[]) => X +>obj.foo(1, 2, ...a) : X +>obj.foo : (x: number, y: number, ...z: string[]) => X +>obj : X +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] + +obj.foo(1, 2, ...a).foo(1, 2, ...a, "abc"); +>obj.foo(1, 2, ...a).foo(1, 2, ...a, "abc") : X +>obj.foo(1, 2, ...a).foo : (x: number, y: number, ...z: string[]) => X +>obj.foo(1, 2, ...a) : X +>obj.foo : (x: number, y: number, ...z: string[]) => X +>obj : X +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >...a : string @@ -85,32 +137,89 @@ obj.foo(1, 2, ...a, "abc"); >"abc" : "abc" (obj.foo)(1, 2, "abc"); ->(obj.foo)(1, 2, "abc") : any ->(obj.foo) : (x: number, y: number, ...z: string[]) => any ->obj.foo : (x: number, y: number, ...z: string[]) => any +>(obj.foo)(1, 2, "abc") : X +>(obj.foo) : (x: number, y: number, ...z: string[]) => X +>obj.foo : (x: number, y: number, ...z: string[]) => X >obj : X ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >"abc" : "abc" (obj.foo)(1, 2, ...a); ->(obj.foo)(1, 2, ...a) : any ->(obj.foo) : (x: number, y: number, ...z: string[]) => any ->obj.foo : (x: number, y: number, ...z: string[]) => any +>(obj.foo)(1, 2, ...a) : X +>(obj.foo) : (x: number, y: number, ...z: string[]) => X +>obj.foo : (x: number, y: number, ...z: string[]) => X >obj : X ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >...a : string >a : string[] (obj.foo)(1, 2, ...a, "abc"); ->(obj.foo)(1, 2, ...a, "abc") : any ->(obj.foo) : (x: number, y: number, ...z: string[]) => any ->obj.foo : (x: number, y: number, ...z: string[]) => any +>(obj.foo)(1, 2, ...a, "abc") : X +>(obj.foo) : (x: number, y: number, ...z: string[]) => X +>obj.foo : (x: number, y: number, ...z: string[]) => X >obj : X ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] +>"abc" : "abc" + +((obj.foo)(1, 2, ...a).foo)(1, 2, "abc"); +>((obj.foo)(1, 2, ...a).foo)(1, 2, "abc") : X +>((obj.foo)(1, 2, ...a).foo) : (x: number, y: number, ...z: string[]) => X +>(obj.foo)(1, 2, ...a).foo : (x: number, y: number, ...z: string[]) => X +>(obj.foo)(1, 2, ...a) : X +>(obj.foo) : (x: number, y: number, ...z: string[]) => X +>obj.foo : (x: number, y: number, ...z: string[]) => X +>obj : X +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>"abc" : "abc" + +((obj.foo)(1, 2, ...a).foo)(1, 2, ...a); +>((obj.foo)(1, 2, ...a).foo)(1, 2, ...a) : X +>((obj.foo)(1, 2, ...a).foo) : (x: number, y: number, ...z: string[]) => X +>(obj.foo)(1, 2, ...a).foo : (x: number, y: number, ...z: string[]) => X +>(obj.foo)(1, 2, ...a) : X +>(obj.foo) : (x: number, y: number, ...z: string[]) => X +>obj.foo : (x: number, y: number, ...z: string[]) => X +>obj : X +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] + +((obj.foo)(1, 2, ...a).foo)(1, 2, ...a, "abc"); +>((obj.foo)(1, 2, ...a).foo)(1, 2, ...a, "abc") : X +>((obj.foo)(1, 2, ...a).foo) : (x: number, y: number, ...z: string[]) => X +>(obj.foo)(1, 2, ...a).foo : (x: number, y: number, ...z: string[]) => X +>(obj.foo)(1, 2, ...a) : X +>(obj.foo) : (x: number, y: number, ...z: string[]) => X +>obj.foo : (x: number, y: number, ...z: string[]) => X +>obj : X +>foo : (x: number, y: number, ...z: string[]) => X +>1 : 1 +>2 : 2 +>...a : string +>a : string[] +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >...a : string @@ -118,35 +227,35 @@ obj.foo(1, 2, ...a, "abc"); >"abc" : "abc" xa[1].foo(1, 2, "abc"); ->xa[1].foo(1, 2, "abc") : any ->xa[1].foo : (x: number, y: number, ...z: string[]) => any +>xa[1].foo(1, 2, "abc") : X +>xa[1].foo : (x: number, y: number, ...z: string[]) => X >xa[1] : X >xa : X[] >1 : 1 ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >"abc" : "abc" xa[1].foo(1, 2, ...a); ->xa[1].foo(1, 2, ...a) : any ->xa[1].foo : (x: number, y: number, ...z: string[]) => any +>xa[1].foo(1, 2, ...a) : X +>xa[1].foo : (x: number, y: number, ...z: string[]) => X >xa[1] : X >xa : X[] >1 : 1 ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >...a : string >a : string[] xa[1].foo(1, 2, ...a, "abc"); ->xa[1].foo(1, 2, ...a, "abc") : any ->xa[1].foo : (x: number, y: number, ...z: string[]) => any +>xa[1].foo(1, 2, ...a, "abc") : X +>xa[1].foo : (x: number, y: number, ...z: string[]) => X >xa[1] : X >xa : X[] >1 : 1 ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X >1 : 1 >2 : 2 >...a : string @@ -158,11 +267,11 @@ xa[1].foo(1, 2, ...a, "abc"); >(xa[1].foo) : Function >xa[1].foo : Function >Function : Function ->xa[1].foo : (x: number, y: number, ...z: string[]) => any +>xa[1].foo : (x: number, y: number, ...z: string[]) => X >xa[1] : X >xa : X[] >1 : 1 ->foo : (x: number, y: number, ...z: string[]) => any +>foo : (x: number, y: number, ...z: string[]) => X >...[1, 2, "abc"] : string | number >[1, 2, "abc"] : (string | number)[] >1 : 1 diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread.ts index 245028db3d4..b1e2ee75784 100644 --- a/tests/cases/conformance/expressions/functionCalls/callWithSpread.ts +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread.ts @@ -1,5 +1,5 @@ interface X { - foo(x: number, y: number, ...z: string[]); + foo(x: number, y: number, ...z: string[]): X; } function foo(x: number, y: number, ...z: string[]) { @@ -18,10 +18,18 @@ obj.foo(1, 2, "abc"); obj.foo(1, 2, ...a); obj.foo(1, 2, ...a, "abc"); +obj.foo(1, 2, ...a).foo(1, 2, "abc"); +obj.foo(1, 2, ...a).foo(1, 2, ...a); +obj.foo(1, 2, ...a).foo(1, 2, ...a, "abc"); + (obj.foo)(1, 2, "abc"); (obj.foo)(1, 2, ...a); (obj.foo)(1, 2, ...a, "abc"); +((obj.foo)(1, 2, ...a).foo)(1, 2, "abc"); +((obj.foo)(1, 2, ...a).foo)(1, 2, ...a); +((obj.foo)(1, 2, ...a).foo)(1, 2, ...a, "abc"); + xa[1].foo(1, 2, "abc"); xa[1].foo(1, 2, ...a); xa[1].foo(1, 2, ...a, "abc"); From 1c004bf317a3e9103572668191055ba1c86f1788 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Thu, 3 Nov 2016 21:13:41 -0700 Subject: [PATCH 09/27] Port #12027, #11980 and #11932 to master (#12037) * add test for the fix for overwrite emitting error * cr feedback --- src/compiler/core.ts | 12 +++++++++ src/compiler/diagnosticMessages.json | 4 +++ src/compiler/program.ts | 25 ++++++++++++++----- src/compiler/types.ts | 1 + src/harness/fourslash.ts | 13 +++++++++- .../unittests/tsserverProjectSystem.ts | 24 ++++++++++++++++++ src/server/project.ts | 4 +++ ...sWhenEmitBlockingErrorOnOtherFile.baseline | 3 ++- .../declarationFileOverwriteError.errors.txt | 2 ++ ...rationFileOverwriteErrorWithOut.errors.txt | 2 ++ .../exportDefaultInJsFile01.errors.txt | 2 ++ .../exportDefaultInJsFile02.errors.txt | 2 ++ ...tionAmbientVarDeclarationSyntax.errors.txt | 2 ++ ...CompilationEmitBlockedCorrectly.errors.txt | 2 ++ .../jsFileCompilationEnumSyntax.errors.txt | 2 ++ ...onsWithJsFileReferenceWithNoOut.errors.txt | 2 ++ ...mpilationExportAssignmentSyntax.errors.txt | 2 ++ ...tionHeritageClauseSyntaxOfClass.errors.txt | 2 ++ ...leCompilationImportEqualsSyntax.errors.txt | 2 ++ ...sFileCompilationInterfaceSyntax.errors.txt | 2 ++ .../jsFileCompilationModuleSyntax.errors.txt | 2 ++ ...onsWithJsFileReferenceWithNoOut.errors.txt | 2 ++ ...ileCompilationOptionalParameter.errors.txt | 2 ++ ...lationPublicMethodSyntaxOfClass.errors.txt | 2 ++ ...pilationPublicParameterModifier.errors.txt | 2 ++ ...ationReturnTypeSyntaxOfFunction.errors.txt | 2 ++ .../jsFileCompilationSyntaxError.errors.txt | 2 ++ ...sFileCompilationTypeAliasSyntax.errors.txt | 2 ++ ...ilationTypeArgumentSyntaxOfCall.errors.txt | 2 ++ ...jsFileCompilationTypeAssertions.errors.txt | 2 ++ ...sFileCompilationTypeOfParameter.errors.txt | 2 ++ ...ationTypeParameterSyntaxOfClass.errors.txt | 2 ++ ...onTypeParameterSyntaxOfFunction.errors.txt | 2 ++ ...sFileCompilationTypeSyntaxOfVar.errors.txt | 2 ++ ...hDeclarationEmitPathSameAsInput.errors.txt | 2 ++ ...lationWithJsEmitPathSameAsInput.errors.txt | 2 ++ ...sFileCompilationWithMapFileAsJs.errors.txt | 2 ++ ...hMapFileAsJsWithInlineSourceMap.errors.txt | 2 ++ ...rationFileNameSameAsInputJsFile.errors.txt | 2 ++ ...ithOutFileNameSameAsInputJsFile.errors.txt | 2 ++ .../jsFileCompilationWithoutOut.errors.txt | 2 ++ ...eNameDtsNotSpecifiedWithAllowJs.errors.txt | 2 ++ ...eNameDtsNotSpecifiedWithAllowJs.errors.txt | 2 ++ 43 files changed, 148 insertions(+), 8 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index dd71877930a..8175730159b 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1127,6 +1127,18 @@ namespace ts { }; } + export function createCompilerDiagnosticFromMessageChain(chain: DiagnosticMessageChain): Diagnostic { + return { + file: undefined, + start: undefined, + length: undefined, + + code: chain.code, + category: chain.category, + messageText: chain.next ? chain : chain.messageText + }; + } + export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: any[]): DiagnosticMessageChain; export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage): DiagnosticMessageChain { let text = getLocaleSpecificMessage(message); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5290782c156..9a353e6fb36 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3158,5 +3158,9 @@ "Implement inherited abstract class": { "category": "Message", "code": 90007 + }, + "Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig": { + "category": "Error", + "code": 90009 } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 82d274e0487..dcb9cce0adb 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -239,11 +239,11 @@ namespace ts { const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); const fileName = diagnostic.file.fileName; const relativeFileName = convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)); - output += `${ relativeFileName }(${ line + 1 },${ character + 1 }): `; + output += `${relativeFileName}(${line + 1},${character + 1}): `; } const category = DiagnosticCategory[diagnostic.category].toLowerCase(); - output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) }${ host.getNewLine() }`; + output += `${category} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine())}${host.getNewLine()}`; } return output; } @@ -1685,13 +1685,24 @@ namespace ts { const emitFilePath = toPath(emitFileName, currentDirectory, getCanonicalFileName); // Report error if the output overwrites input file if (filesByName.contains(emitFilePath)) { - createEmitBlockingDiagnostics(emitFileName, Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file); + if (options.noEmitOverwritenFiles && !options.out && !options.outDir && !options.outFile) { + blockEmittingOfFile(emitFileName); + } + else { + let chain: DiagnosticMessageChain; + if (!options.configFilePath) { + // The program is from either an inferred project or an external project + chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); + } + chain = chainDiagnosticMessages(chain, Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file, emitFileName); + blockEmittingOfFile(emitFileName, createCompilerDiagnosticFromMessageChain(chain)); + } } // Report error if multiple files write into same file if (emitFilesSeen.contains(emitFilePath)) { // Already seen the same emit file - report error - createEmitBlockingDiagnostics(emitFileName, Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files); + blockEmittingOfFile(emitFileName, createCompilerDiagnostic(Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName)); } else { emitFilesSeen.set(emitFilePath, true); @@ -1700,9 +1711,11 @@ namespace ts { } } - function createEmitBlockingDiagnostics(emitFileName: string, message: DiagnosticMessage) { + function blockEmittingOfFile(emitFileName: string, diag?: Diagnostic) { hasEmitBlockingDiagnostics.set(toPath(emitFileName, currentDirectory, getCanonicalFileName), true); - programDiagnostics.add(createCompilerDiagnostic(message, emitFileName)); + if (diag) { + programDiagnostics.add(diag); + } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b865beca76b..5536a818df5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3058,6 +3058,7 @@ namespace ts { moduleResolution?: ModuleResolutionKind; newLine?: NewLineKind; noEmit?: boolean; + /*@internal*/noEmitOverwritenFiles?: boolean; noEmitHelpers?: boolean; noEmitOnError?: boolean; noErrorTruncation?: boolean; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index b008ca65370..ae32fe3db16 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1253,7 +1253,18 @@ namespace FourSlash { resultString += "Diagnostics:" + Harness.IO.newLine(); const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram()); for (const diagnostic of diagnostics) { - resultString += " " + diagnostic.messageText + Harness.IO.newLine(); + if (typeof diagnostic.messageText !== "string") { + let chainedMessage = diagnostic.messageText; + let indentation = " "; + while (chainedMessage) { + resultString += indentation + chainedMessage.messageText + Harness.IO.newLine(); + chainedMessage = chainedMessage.next; + indentation = indentation + " "; + } + } + else { + resultString += " " + diagnostic.messageText + Harness.IO.newLine(); + } } } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 870926a8c55..15cfa3f8c8e 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2505,4 +2505,28 @@ namespace ts.projectSystem { checkProjectActualFiles(projectService.inferredProjects[0], [f.path]); }); }); + + describe("No overwrite emit error", () => { + it("for inferred project", () => { + const f1 = { + path: "/a/b/f1.js", + content: "function test1() { }" + }; + const host = createServerHost([f1, libFile]); + const session = createSession(host); + openFilesForSession([f1], session); + + const projectService = session.getProjectService(); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + const projectName = projectService.inferredProjects[0].getProjectName(); + + const diags = session.executeCommand({ + type: "request", + command: server.CommandNames.CompilerOptionsDiagnosticsFull, + seq: 2, + arguments: { projectFileName: projectName } + }).response; + assert.isTrue(diags.length === 0); + }); + }); } \ No newline at end of file diff --git a/src/server/project.ts b/src/server/project.ts index 457f5e2b261..563b0456910 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -161,6 +161,10 @@ namespace ts.server { this.compilerOptions.allowNonTsExtensions = true; } + if (this.projectKind === ProjectKind.Inferred) { + this.compilerOptions.noEmitOverwritenFiles = true; + } + if (languageServiceEnabled) { this.enableLanguageService(); } diff --git a/tests/baselines/reference/compileOnSaveWorksWhenEmitBlockingErrorOnOtherFile.baseline b/tests/baselines/reference/compileOnSaveWorksWhenEmitBlockingErrorOnOtherFile.baseline index a088006d145..f8b479e6d7b 100644 --- a/tests/baselines/reference/compileOnSaveWorksWhenEmitBlockingErrorOnOtherFile.baseline +++ b/tests/baselines/reference/compileOnSaveWorksWhenEmitBlockingErrorOnOtherFile.baseline @@ -1,6 +1,7 @@ EmitSkipped: true Diagnostics: - Cannot write file '/tests/cases/fourslash/b.js' because it would overwrite input file. + Cannot write file '/tests/cases/fourslash/b.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig EmitSkipped: false FileName : /tests/cases/fourslash/a.js diff --git a/tests/baselines/reference/declarationFileOverwriteError.errors.txt b/tests/baselines/reference/declarationFileOverwriteError.errors.txt index 1974976dee1..211469778b1 100644 --- a/tests/baselines/reference/declarationFileOverwriteError.errors.txt +++ b/tests/baselines/reference/declarationFileOverwriteError.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.d.ts' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/compiler/a.d.ts' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.d.ts (0 errors) ==== declare class c { diff --git a/tests/baselines/reference/declarationFileOverwriteErrorWithOut.errors.txt b/tests/baselines/reference/declarationFileOverwriteErrorWithOut.errors.txt index 658465de9c2..ea4a93b3b12 100644 --- a/tests/baselines/reference/declarationFileOverwriteErrorWithOut.errors.txt +++ b/tests/baselines/reference/declarationFileOverwriteErrorWithOut.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/compiler/out.d.ts' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/compiler/out.d.ts' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/out.d.ts (0 errors) ==== declare class c { diff --git a/tests/baselines/reference/exportDefaultInJsFile01.errors.txt b/tests/baselines/reference/exportDefaultInJsFile01.errors.txt index 34035e1e14e..0565c8bd61e 100644 --- a/tests/baselines/reference/exportDefaultInJsFile01.errors.txt +++ b/tests/baselines/reference/exportDefaultInJsFile01.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/conformance/salsa/myFile01.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/conformance/salsa/myFile01.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/conformance/salsa/myFile01.js (0 errors) ==== export default "hello"; \ No newline at end of file diff --git a/tests/baselines/reference/exportDefaultInJsFile02.errors.txt b/tests/baselines/reference/exportDefaultInJsFile02.errors.txt index 5e17306e066..a74fbacfcfd 100644 --- a/tests/baselines/reference/exportDefaultInJsFile02.errors.txt +++ b/tests/baselines/reference/exportDefaultInJsFile02.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/conformance/salsa/myFile02.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/conformance/salsa/myFile02.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/conformance/salsa/myFile02.js (0 errors) ==== export default "hello"; \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilationAmbientVarDeclarationSyntax.errors.txt b/tests/baselines/reference/jsFileCompilationAmbientVarDeclarationSyntax.errors.txt index 19bfd5d1c02..039834ff702 100644 --- a/tests/baselines/reference/jsFileCompilationAmbientVarDeclarationSyntax.errors.txt +++ b/tests/baselines/reference/jsFileCompilationAmbientVarDeclarationSyntax.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,1): error TS8009: 'declare' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== declare var v; ~~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationEmitBlockedCorrectly.errors.txt b/tests/baselines/reference/jsFileCompilationEmitBlockedCorrectly.errors.txt index 0aa9d5733d5..75bcf88b10a 100644 --- a/tests/baselines/reference/jsFileCompilationEmitBlockedCorrectly.errors.txt +++ b/tests/baselines/reference/jsFileCompilationEmitBlockedCorrectly.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig error TS5056: Cannot write file 'tests/cases/compiler/a.js' because it would be overwritten by multiple input files. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5056: Cannot write file 'tests/cases/compiler/a.js' because it would be overwritten by multiple input files. ==== tests/cases/compiler/a.ts (0 errors) ==== class c { diff --git a/tests/baselines/reference/jsFileCompilationEnumSyntax.errors.txt b/tests/baselines/reference/jsFileCompilationEnumSyntax.errors.txt index 538dfb38972..c6da8931d5e 100644 --- a/tests/baselines/reference/jsFileCompilationEnumSyntax.errors.txt +++ b/tests/baselines/reference/jsFileCompilationEnumSyntax.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,6): error TS8015: 'enum declarations' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== enum E { } ~ diff --git a/tests/baselines/reference/jsFileCompilationErrorOnDeclarationsWithJsFileReferenceWithNoOut.errors.txt b/tests/baselines/reference/jsFileCompilationErrorOnDeclarationsWithJsFileReferenceWithNoOut.errors.txt index 641731936f8..54e91c5d196 100644 --- a/tests/baselines/reference/jsFileCompilationErrorOnDeclarationsWithJsFileReferenceWithNoOut.errors.txt +++ b/tests/baselines/reference/jsFileCompilationErrorOnDeclarationsWithJsFileReferenceWithNoOut.errors.txt @@ -1,9 +1,11 @@ error TS5053: Option 'allowJs' cannot be specified with option 'declaration'. error TS5055: Cannot write file 'tests/cases/compiler/c.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'. !!! error TS5055: Cannot write file 'tests/cases/compiler/c.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.ts (0 errors) ==== class c { } diff --git a/tests/baselines/reference/jsFileCompilationExportAssignmentSyntax.errors.txt b/tests/baselines/reference/jsFileCompilationExportAssignmentSyntax.errors.txt index f537941c55c..babbeea8004 100644 --- a/tests/baselines/reference/jsFileCompilationExportAssignmentSyntax.errors.txt +++ b/tests/baselines/reference/jsFileCompilationExportAssignmentSyntax.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,1): error TS8003: 'export=' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== export = b; ~~~~~~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationHeritageClauseSyntaxOfClass.errors.txt b/tests/baselines/reference/jsFileCompilationHeritageClauseSyntaxOfClass.errors.txt index 33b8a45f1aa..3b30663308f 100644 --- a/tests/baselines/reference/jsFileCompilationHeritageClauseSyntaxOfClass.errors.txt +++ b/tests/baselines/reference/jsFileCompilationHeritageClauseSyntaxOfClass.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,9): error TS8005: 'implements clauses' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== class C implements D { } ~~~~~~~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationImportEqualsSyntax.errors.txt b/tests/baselines/reference/jsFileCompilationImportEqualsSyntax.errors.txt index b4161367037..a064f53e92f 100644 --- a/tests/baselines/reference/jsFileCompilationImportEqualsSyntax.errors.txt +++ b/tests/baselines/reference/jsFileCompilationImportEqualsSyntax.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,1): error TS8002: 'import ... =' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== import a = b; ~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationInterfaceSyntax.errors.txt b/tests/baselines/reference/jsFileCompilationInterfaceSyntax.errors.txt index 17fb8fcb187..9e53438c732 100644 --- a/tests/baselines/reference/jsFileCompilationInterfaceSyntax.errors.txt +++ b/tests/baselines/reference/jsFileCompilationInterfaceSyntax.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,11): error TS8006: 'interface declarations' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== interface I { } ~ diff --git a/tests/baselines/reference/jsFileCompilationModuleSyntax.errors.txt b/tests/baselines/reference/jsFileCompilationModuleSyntax.errors.txt index 662028c53ed..6952c0055c0 100644 --- a/tests/baselines/reference/jsFileCompilationModuleSyntax.errors.txt +++ b/tests/baselines/reference/jsFileCompilationModuleSyntax.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,8): error TS8007: 'module declarations' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== module M { } ~ diff --git a/tests/baselines/reference/jsFileCompilationNoErrorWithoutDeclarationsWithJsFileReferenceWithNoOut.errors.txt b/tests/baselines/reference/jsFileCompilationNoErrorWithoutDeclarationsWithJsFileReferenceWithNoOut.errors.txt index f2f4142b993..888310414f2 100644 --- a/tests/baselines/reference/jsFileCompilationNoErrorWithoutDeclarationsWithJsFileReferenceWithNoOut.errors.txt +++ b/tests/baselines/reference/jsFileCompilationNoErrorWithoutDeclarationsWithJsFileReferenceWithNoOut.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/compiler/c.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/compiler/c.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.ts (0 errors) ==== class c { } diff --git a/tests/baselines/reference/jsFileCompilationOptionalParameter.errors.txt b/tests/baselines/reference/jsFileCompilationOptionalParameter.errors.txt index 295f827dd2d..15bfe2281d9 100644 --- a/tests/baselines/reference/jsFileCompilationOptionalParameter.errors.txt +++ b/tests/baselines/reference/jsFileCompilationOptionalParameter.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,13): error TS8009: '?' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== function F(p?) { } ~ diff --git a/tests/baselines/reference/jsFileCompilationPublicMethodSyntaxOfClass.errors.txt b/tests/baselines/reference/jsFileCompilationPublicMethodSyntaxOfClass.errors.txt index d67c9baea70..af95c136205 100644 --- a/tests/baselines/reference/jsFileCompilationPublicMethodSyntaxOfClass.errors.txt +++ b/tests/baselines/reference/jsFileCompilationPublicMethodSyntaxOfClass.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(2,5): error TS8009: 'public' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== class C { public foo() { diff --git a/tests/baselines/reference/jsFileCompilationPublicParameterModifier.errors.txt b/tests/baselines/reference/jsFileCompilationPublicParameterModifier.errors.txt index bc4913f6217..9314e1da807 100644 --- a/tests/baselines/reference/jsFileCompilationPublicParameterModifier.errors.txt +++ b/tests/baselines/reference/jsFileCompilationPublicParameterModifier.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,23): error TS8012: 'parameter modifiers' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== class C { constructor(public x) { }} ~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationReturnTypeSyntaxOfFunction.errors.txt b/tests/baselines/reference/jsFileCompilationReturnTypeSyntaxOfFunction.errors.txt index 6dad5a29485..acae950d081 100644 --- a/tests/baselines/reference/jsFileCompilationReturnTypeSyntaxOfFunction.errors.txt +++ b/tests/baselines/reference/jsFileCompilationReturnTypeSyntaxOfFunction.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,15): error TS8010: 'types' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== function F(): number { } ~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationSyntaxError.errors.txt b/tests/baselines/reference/jsFileCompilationSyntaxError.errors.txt index d98a1e7e7bb..eb4c114d3d0 100644 --- a/tests/baselines/reference/jsFileCompilationSyntaxError.errors.txt +++ b/tests/baselines/reference/jsFileCompilationSyntaxError.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (0 errors) ==== /** * @type {number} diff --git a/tests/baselines/reference/jsFileCompilationTypeAliasSyntax.errors.txt b/tests/baselines/reference/jsFileCompilationTypeAliasSyntax.errors.txt index 2b5112e1ce2..74978eddf8c 100644 --- a/tests/baselines/reference/jsFileCompilationTypeAliasSyntax.errors.txt +++ b/tests/baselines/reference/jsFileCompilationTypeAliasSyntax.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,6): error TS8008: 'type aliases' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== type a = b; ~ diff --git a/tests/baselines/reference/jsFileCompilationTypeArgumentSyntaxOfCall.errors.txt b/tests/baselines/reference/jsFileCompilationTypeArgumentSyntaxOfCall.errors.txt index 8ac59196ed9..f53ec55d2b1 100644 --- a/tests/baselines/reference/jsFileCompilationTypeArgumentSyntaxOfCall.errors.txt +++ b/tests/baselines/reference/jsFileCompilationTypeArgumentSyntaxOfCall.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,5): error TS8011: 'type arguments' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== Foo(); ~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationTypeAssertions.errors.txt b/tests/baselines/reference/jsFileCompilationTypeAssertions.errors.txt index 662eea4d405..be1e6d32436 100644 --- a/tests/baselines/reference/jsFileCompilationTypeAssertions.errors.txt +++ b/tests/baselines/reference/jsFileCompilationTypeAssertions.errors.txt @@ -1,9 +1,11 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,10): error TS17008: JSX element 'string' has no corresponding closing tag. tests/cases/compiler/a.js(1,27): error TS1005: 'undefined; ~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationTypeOfParameter.errors.txt b/tests/baselines/reference/jsFileCompilationTypeOfParameter.errors.txt index 680b32a64f1..811c0793ffe 100644 --- a/tests/baselines/reference/jsFileCompilationTypeOfParameter.errors.txt +++ b/tests/baselines/reference/jsFileCompilationTypeOfParameter.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,15): error TS8010: 'types' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== function F(a: number) { } ~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationTypeParameterSyntaxOfClass.errors.txt b/tests/baselines/reference/jsFileCompilationTypeParameterSyntaxOfClass.errors.txt index 161c832ffd5..0fe902aa661 100644 --- a/tests/baselines/reference/jsFileCompilationTypeParameterSyntaxOfClass.errors.txt +++ b/tests/baselines/reference/jsFileCompilationTypeParameterSyntaxOfClass.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,9): error TS8004: 'type parameter declarations' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== class C { } ~ diff --git a/tests/baselines/reference/jsFileCompilationTypeParameterSyntaxOfFunction.errors.txt b/tests/baselines/reference/jsFileCompilationTypeParameterSyntaxOfFunction.errors.txt index d7626f68564..bfc4c7be26a 100644 --- a/tests/baselines/reference/jsFileCompilationTypeParameterSyntaxOfFunction.errors.txt +++ b/tests/baselines/reference/jsFileCompilationTypeParameterSyntaxOfFunction.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,12): error TS8004: 'type parameter declarations' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== function F() { } ~ diff --git a/tests/baselines/reference/jsFileCompilationTypeSyntaxOfVar.errors.txt b/tests/baselines/reference/jsFileCompilationTypeSyntaxOfVar.errors.txt index 2c6ac3771be..65333751780 100644 --- a/tests/baselines/reference/jsFileCompilationTypeSyntaxOfVar.errors.txt +++ b/tests/baselines/reference/jsFileCompilationTypeSyntaxOfVar.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig tests/cases/compiler/a.js(1,8): error TS8010: 'types' can only be used in a .ts file. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.js (1 errors) ==== var v: () => number; ~~~~~~~~~~~~ diff --git a/tests/baselines/reference/jsFileCompilationWithDeclarationEmitPathSameAsInput.errors.txt b/tests/baselines/reference/jsFileCompilationWithDeclarationEmitPathSameAsInput.errors.txt index 9e9c2adb0ef..4170e818fd7 100644 --- a/tests/baselines/reference/jsFileCompilationWithDeclarationEmitPathSameAsInput.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithDeclarationEmitPathSameAsInput.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.d.ts' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/compiler/a.d.ts' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.ts (0 errors) ==== class c { } diff --git a/tests/baselines/reference/jsFileCompilationWithJsEmitPathSameAsInput.errors.txt b/tests/baselines/reference/jsFileCompilationWithJsEmitPathSameAsInput.errors.txt index 4cc2cc2ab45..8004efd02ef 100644 --- a/tests/baselines/reference/jsFileCompilationWithJsEmitPathSameAsInput.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithJsEmitPathSameAsInput.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig error TS5056: Cannot write file 'tests/cases/compiler/a.js' because it would be overwritten by multiple input files. !!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5056: Cannot write file 'tests/cases/compiler/a.js' because it would be overwritten by multiple input files. ==== tests/cases/compiler/a.ts (0 errors) ==== class c { diff --git a/tests/baselines/reference/jsFileCompilationWithMapFileAsJs.errors.txt b/tests/baselines/reference/jsFileCompilationWithMapFileAsJs.errors.txt index 06186b9f0b2..069c562f29b 100644 --- a/tests/baselines/reference/jsFileCompilationWithMapFileAsJs.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithMapFileAsJs.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig error TS6054: File 'tests/cases/compiler/b.js.map' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'. !!! error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS6054: File 'tests/cases/compiler/b.js.map' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'. ==== tests/cases/compiler/a.ts (0 errors) ==== diff --git a/tests/baselines/reference/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.errors.txt b/tests/baselines/reference/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.errors.txt index 06186b9f0b2..069c562f29b 100644 --- a/tests/baselines/reference/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.errors.txt @@ -1,8 +1,10 @@ error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig error TS6054: File 'tests/cases/compiler/b.js.map' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'. !!! error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS6054: File 'tests/cases/compiler/b.js.map' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'. ==== tests/cases/compiler/a.ts (0 errors) ==== diff --git a/tests/baselines/reference/jsFileCompilationWithOutDeclarationFileNameSameAsInputJsFile.errors.txt b/tests/baselines/reference/jsFileCompilationWithOutDeclarationFileNameSameAsInputJsFile.errors.txt index 10c7b8c90dd..0a4f0cdf1a4 100644 --- a/tests/baselines/reference/jsFileCompilationWithOutDeclarationFileNameSameAsInputJsFile.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithOutDeclarationFileNameSameAsInputJsFile.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/compiler/b.d.ts' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/compiler/b.d.ts' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.ts (0 errors) ==== class c { } diff --git a/tests/baselines/reference/jsFileCompilationWithOutFileNameSameAsInputJsFile.errors.txt b/tests/baselines/reference/jsFileCompilationWithOutFileNameSameAsInputJsFile.errors.txt index 0f6852b21a0..3f72a8113ef 100644 --- a/tests/baselines/reference/jsFileCompilationWithOutFileNameSameAsInputJsFile.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithOutFileNameSameAsInputJsFile.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.ts (0 errors) ==== class c { } diff --git a/tests/baselines/reference/jsFileCompilationWithoutOut.errors.txt b/tests/baselines/reference/jsFileCompilationWithoutOut.errors.txt index 0f6852b21a0..3f72a8113ef 100644 --- a/tests/baselines/reference/jsFileCompilationWithoutOut.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithoutOut.errors.txt @@ -1,7 +1,9 @@ error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== tests/cases/compiler/a.ts (0 errors) ==== class c { } diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt index ac25edc1bd5..668f037a03b 100644 --- a/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt +++ b/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt @@ -1,9 +1,11 @@ error TS5053: Option 'allowJs' cannot be specified with option 'declaration'. error TS5055: Cannot write file 'SameNameDTsNotSpecifiedWithAllowJs/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'. !!! error TS5055: Cannot write file 'SameNameDTsNotSpecifiedWithAllowJs/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== SameNameDTsNotSpecifiedWithAllowJs/a.d.ts (0 errors) ==== declare var a: number; ==== SameNameDTsNotSpecifiedWithAllowJs/a.js (0 errors) ==== diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt index ac25edc1bd5..668f037a03b 100644 --- a/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt +++ b/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt @@ -1,9 +1,11 @@ error TS5053: Option 'allowJs' cannot be specified with option 'declaration'. error TS5055: Cannot write file 'SameNameDTsNotSpecifiedWithAllowJs/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig !!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'. !!! error TS5055: Cannot write file 'SameNameDTsNotSpecifiedWithAllowJs/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig ==== SameNameDTsNotSpecifiedWithAllowJs/a.d.ts (0 errors) ==== declare var a: number; ==== SameNameDTsNotSpecifiedWithAllowJs/a.js (0 errors) ==== From ed4fead087ab0fea1811e4b42b6d8e599ee13f1e Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 4 Nov 2016 21:54:22 -0700 Subject: [PATCH 10/27] add missing bind calls to properly set parent on token nodes (#12057) --- src/compiler/binder.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index c1011e57568..1d721e2db90 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1234,9 +1234,11 @@ namespace ts { const postExpressionLabel = createBranchLabel(); bindCondition(node.condition, trueLabel, falseLabel); currentFlow = finishFlowLabel(trueLabel); + bind(node.questionToken); bind(node.whenTrue); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(falseLabel); + bind(node.colonToken); bind(node.whenFalse); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(postExpressionLabel); From 61b9da548a6eb8d6b11849d129996625968833f4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Nov 2016 08:20:02 -0700 Subject: [PATCH 11/27] Cache generic signature instantiations --- src/compiler/checker.ts | 8 +++++++- src/compiler/types.ts | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0f2c642124a..9647077d943 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4232,7 +4232,7 @@ namespace ts { for (const baseSig of baseSignatures) { const typeParamCount = baseSig.typeParameters ? baseSig.typeParameters.length : 0; if (typeParamCount === typeArgCount) { - const sig = typeParamCount ? getSignatureInstantiation(baseSig, typeArguments) : cloneSignature(baseSig); + const sig = typeParamCount ? createSignatureInstantiation(baseSig, typeArguments) : cloneSignature(baseSig); sig.typeParameters = classType.localTypeParameters; sig.resolvedReturnType = classType; result.push(sig); @@ -4982,6 +4982,12 @@ namespace ts { } function getSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature { + const instantiations = signature.instantiations || (signature.instantiations = createMap()); + const id = getTypeListId(typeArguments); + return instantiations[id] || (instantiations[id] = createSignatureInstantiation(signature, typeArguments)); + } + + function createSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature { return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), /*eraseTypeParameters*/ true); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5536a818df5..37a3cc466a0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2923,6 +2923,8 @@ namespace ts { isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison /* @internal */ typePredicate?: TypePredicate; + /* @internal */ + instantiations?: Map; // Generic signature instantiation cache } export const enum IndexKind { From 4c1e4169bded1a3e6fbfb72edf8ae3a47e78b5ad Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Nov 2016 08:23:42 -0700 Subject: [PATCH 12/27] Accept new baselines --- tests/baselines/reference/promisePermutations.errors.txt | 4 ---- tests/baselines/reference/promisePermutations2.errors.txt | 4 ---- tests/baselines/reference/promisePermutations3.errors.txt | 4 ---- 3 files changed, 12 deletions(-) diff --git a/tests/baselines/reference/promisePermutations.errors.txt b/tests/baselines/reference/promisePermutations.errors.txt index 65fa0981643..13fc0718596 100644 --- a/tests/baselines/reference/promisePermutations.errors.txt +++ b/tests/baselines/reference/promisePermutations.errors.txt @@ -25,8 +25,6 @@ tests/cases/compiler/promisePermutations.ts(106,19): error TS2345: Argument of t Types of parameters 'cb' and 'value' are incompatible. Type 'string' is not assignable to type '(a: T) => T'. tests/cases/compiler/promisePermutations.ts(109,19): error TS2345: Argument of type '(cb: (a: T) => T) => IPromise' is not assignable to parameter of type '(value: string) => IPromise'. - Types of parameters 'cb' and 'value' are incompatible. - Type 'string' is not assignable to type '(a: T) => T'. tests/cases/compiler/promisePermutations.ts(110,19): error TS2345: Argument of type '(cb: (a: T) => T) => Promise' is not assignable to parameter of type '(value: string) => Promise'. Types of parameters 'cb' and 'value' are incompatible. Type 'string' is not assignable to type '(a: T) => T'. @@ -229,8 +227,6 @@ tests/cases/compiler/promisePermutations.ts(160,21): error TS2345: Argument of t var s7a = r7.then(testFunction7, testFunction7, testFunction7); // error ~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(cb: (a: T) => T) => IPromise' is not assignable to parameter of type '(value: string) => IPromise'. -!!! error TS2345: Types of parameters 'cb' and 'value' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type '(a: T) => T'. var s7b = r7.then(testFunction7P, testFunction7P, testFunction7P); // error ~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(cb: (a: T) => T) => Promise' is not assignable to parameter of type '(value: string) => Promise'. diff --git a/tests/baselines/reference/promisePermutations2.errors.txt b/tests/baselines/reference/promisePermutations2.errors.txt index 0fc6f04911a..b21a3a39208 100644 --- a/tests/baselines/reference/promisePermutations2.errors.txt +++ b/tests/baselines/reference/promisePermutations2.errors.txt @@ -25,8 +25,6 @@ tests/cases/compiler/promisePermutations2.ts(105,19): error TS2345: Argument of Types of parameters 'cb' and 'value' are incompatible. Type 'string' is not assignable to type '(a: T) => T'. tests/cases/compiler/promisePermutations2.ts(108,19): error TS2345: Argument of type '(cb: (a: T) => T) => IPromise' is not assignable to parameter of type '(value: string) => IPromise'. - Types of parameters 'cb' and 'value' are incompatible. - Type 'string' is not assignable to type '(a: T) => T'. tests/cases/compiler/promisePermutations2.ts(109,19): error TS2345: Argument of type '(cb: (a: T) => T) => Promise' is not assignable to parameter of type '(value: string) => Promise'. Types of parameters 'cb' and 'value' are incompatible. Type 'string' is not assignable to type '(a: T) => T'. @@ -228,8 +226,6 @@ tests/cases/compiler/promisePermutations2.ts(159,21): error TS2345: Argument of var s7a = r7.then(testFunction7, testFunction7, testFunction7); // error ~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(cb: (a: T) => T) => IPromise' is not assignable to parameter of type '(value: string) => IPromise'. -!!! error TS2345: Types of parameters 'cb' and 'value' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type '(a: T) => T'. var s7b = r7.then(testFunction7P, testFunction7P, testFunction7P); // error ~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(cb: (a: T) => T) => Promise' is not assignable to parameter of type '(value: string) => Promise'. diff --git a/tests/baselines/reference/promisePermutations3.errors.txt b/tests/baselines/reference/promisePermutations3.errors.txt index a1a1b3f493f..1a33d1083aa 100644 --- a/tests/baselines/reference/promisePermutations3.errors.txt +++ b/tests/baselines/reference/promisePermutations3.errors.txt @@ -28,8 +28,6 @@ tests/cases/compiler/promisePermutations3.ts(105,19): error TS2345: Argument of Types of parameters 'cb' and 'value' are incompatible. Type 'string' is not assignable to type '(a: T) => T'. tests/cases/compiler/promisePermutations3.ts(108,19): error TS2345: Argument of type '(cb: (a: T) => T) => IPromise' is not assignable to parameter of type '(value: string) => IPromise'. - Types of parameters 'cb' and 'value' are incompatible. - Type 'string' is not assignable to type '(a: T) => T'. tests/cases/compiler/promisePermutations3.ts(109,19): error TS2345: Argument of type '(cb: (a: T) => T) => Promise' is not assignable to parameter of type '(value: string) => Promise'. Types of parameters 'cb' and 'value' are incompatible. Type 'string' is not assignable to type '(a: T) => T'. @@ -240,8 +238,6 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of var s7a = r7.then(testFunction7, testFunction7, testFunction7); // error ~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(cb: (a: T) => T) => IPromise' is not assignable to parameter of type '(value: string) => IPromise'. -!!! error TS2345: Types of parameters 'cb' and 'value' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type '(a: T) => T'. var s7b = r7.then(testFunction7P, testFunction7P, testFunction7P); // error ~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(cb: (a: T) => T) => Promise' is not assignable to parameter of type '(value: string) => Promise'. From da7f11fe4bc7a2b95705601590df17a720f8e072 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Nov 2016 17:36:00 -0700 Subject: [PATCH 13/27] Properly instantiate aliasTypeArguments --- src/compiler/checker.ts | 25 ++++++++++++++++--------- src/compiler/types.ts | 1 - 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0f2c642124a..d0028896baa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4164,8 +4164,8 @@ namespace ts { else { mapper = createTypeMapper(typeParameters, typeArguments); members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1); - callSignatures = instantiateList(source.declaredCallSignatures, mapper, instantiateSignature); - constructSignatures = instantiateList(source.declaredConstructSignatures, mapper, instantiateSignature); + callSignatures = instantiateSignatures(source.declaredCallSignatures, mapper); + constructSignatures = instantiateSignatures(source.declaredConstructSignatures, mapper); stringIndexInfo = instantiateIndexInfo(source.declaredStringIndexInfo, mapper); numberIndexInfo = instantiateIndexInfo(source.declaredNumberIndexInfo, mapper); } @@ -4363,8 +4363,8 @@ namespace ts { const symbol = type.symbol; if (type.target) { const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false); - const callSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper, instantiateSignature); - const constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature); + const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper); + const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper); const stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.String), type.mapper); const numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.Number), type.mapper); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); @@ -6037,6 +6037,14 @@ namespace ts { return items; } + function instantiateTypes(types: Type[], mapper: TypeMapper) { + return instantiateList(types, mapper, instantiateType); + } + + function instantiateSignatures(signatures: Signature[], mapper: TypeMapper) { + return instantiateList(signatures, mapper, instantiateSignature); + } + function createUnaryTypeMapper(source: Type, target: Type): TypeMapper { return t => t === source ? target : t; } @@ -6063,7 +6071,6 @@ namespace ts { count == 2 ? createBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) : createArrayTypeMapper(sources, targets); mapper.mappedTypes = sources; - mapper.targetTypes = targets; return mapper; } @@ -6190,7 +6197,7 @@ namespace ts { result.target = type; result.mapper = mapper; result.aliasSymbol = type.aliasSymbol; - result.aliasTypeArguments = mapper.targetTypes; + result.aliasTypeArguments = instantiateTypes(type.aliasTypeArguments, mapper); mapper.instantiations[type.id] = result; return result; } @@ -6266,14 +6273,14 @@ namespace ts { instantiateAnonymousType(type, mapper) : type; } if ((type).objectFlags & ObjectFlags.Reference) { - return createTypeReference((type).target, instantiateList((type).typeArguments, mapper, instantiateType)); + return createTypeReference((type).target, instantiateTypes((type).typeArguments, mapper)); } } if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) { - return getUnionType(instantiateList((type).types, mapper, instantiateType), /*subtypeReduction*/ false, type.aliasSymbol, mapper.targetTypes); + return getUnionType(instantiateTypes((type).types, mapper), /*subtypeReduction*/ false, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)); } if (type.flags & TypeFlags.Intersection) { - return getIntersectionType(instantiateList((type).types, mapper, instantiateType), type.aliasSymbol, mapper.targetTypes); + return getIntersectionType(instantiateTypes((type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)); } if (type.flags & TypeFlags.Index) { return getIndexType(instantiateType((type).type, mapper)); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5536a818df5..f8c77a821a3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2940,7 +2940,6 @@ namespace ts { export interface TypeMapper { (t: TypeParameter): Type; mappedTypes?: Type[]; // Types mapped by this mapper - targetTypes?: Type[]; // Types substituted for mapped types instantiations?: Type[]; // Cache of instantiations created using this type mapper. context?: InferenceContext; // The inference context this mapper was created from. // Only inference mappers have this set (in createInferenceMapper). From adfa271e4487b0e86932f936b53536262db84c35 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Nov 2016 17:36:13 -0700 Subject: [PATCH 14/27] Add regression test --- .../reference/instantiatedTypeAliasDisplay.js | 21 ++++++ .../instantiatedTypeAliasDisplay.symbols | 60 +++++++++++++++++ .../instantiatedTypeAliasDisplay.types | 66 +++++++++++++++++++ .../compiler/instantiatedTypeAliasDisplay.ts | 15 +++++ 4 files changed, 162 insertions(+) create mode 100644 tests/baselines/reference/instantiatedTypeAliasDisplay.js create mode 100644 tests/baselines/reference/instantiatedTypeAliasDisplay.symbols create mode 100644 tests/baselines/reference/instantiatedTypeAliasDisplay.types create mode 100644 tests/cases/compiler/instantiatedTypeAliasDisplay.ts diff --git a/tests/baselines/reference/instantiatedTypeAliasDisplay.js b/tests/baselines/reference/instantiatedTypeAliasDisplay.js new file mode 100644 index 00000000000..86b17262e0f --- /dev/null +++ b/tests/baselines/reference/instantiatedTypeAliasDisplay.js @@ -0,0 +1,21 @@ +//// [instantiatedTypeAliasDisplay.ts] +// Repros from #12066 + +interface X { + a: A; +} +interface Y { + b: B; +} +type Z = X | Y; + +declare function f1(): Z; +declare function f2(a: A, b: B, c: C, d: D): Z; + +const x1 = f1(); // Z +const x2 = f2({}, {}, {}, {}); // Z<{}, string[]> + +//// [instantiatedTypeAliasDisplay.js] +// Repros from #12066 +var x1 = f1(); // Z +var x2 = f2({}, {}, {}, {}); // Z<{}, string[]> diff --git a/tests/baselines/reference/instantiatedTypeAliasDisplay.symbols b/tests/baselines/reference/instantiatedTypeAliasDisplay.symbols new file mode 100644 index 00000000000..3c6f7d2b725 --- /dev/null +++ b/tests/baselines/reference/instantiatedTypeAliasDisplay.symbols @@ -0,0 +1,60 @@ +=== tests/cases/compiler/instantiatedTypeAliasDisplay.ts === +// Repros from #12066 + +interface X { +>X : Symbol(X, Decl(instantiatedTypeAliasDisplay.ts, 0, 0)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 2, 12)) + + a: A; +>a : Symbol(X.a, Decl(instantiatedTypeAliasDisplay.ts, 2, 16)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 2, 12)) +} +interface Y { +>Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 4, 1)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 5, 12)) + + b: B; +>b : Symbol(Y.b, Decl(instantiatedTypeAliasDisplay.ts, 5, 16)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 5, 12)) +} +type Z = X | Y; +>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 7, 1)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 8, 7)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 8, 9)) +>X : Symbol(X, Decl(instantiatedTypeAliasDisplay.ts, 0, 0)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 8, 7)) +>Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 4, 1)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 8, 9)) + +declare function f1(): Z; +>f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 8, 27)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 10, 20)) +>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 7, 1)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 10, 20)) + +declare function f2(a: A, b: B, c: C, d: D): Z; +>f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 10, 39)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 11, 22)) +>C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 11, 25)) +>D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 11, 28)) +>E : Symbol(E, Decl(instantiatedTypeAliasDisplay.ts, 11, 31)) +>a : Symbol(a, Decl(instantiatedTypeAliasDisplay.ts, 11, 35)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20)) +>b : Symbol(b, Decl(instantiatedTypeAliasDisplay.ts, 11, 40)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 11, 22)) +>c : Symbol(c, Decl(instantiatedTypeAliasDisplay.ts, 11, 46)) +>C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 11, 25)) +>d : Symbol(d, Decl(instantiatedTypeAliasDisplay.ts, 11, 52)) +>D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 11, 28)) +>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 7, 1)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20)) + +const x1 = f1(); // Z +>x1 : Symbol(x1, Decl(instantiatedTypeAliasDisplay.ts, 13, 5)) +>f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 8, 27)) + +const x2 = f2({}, {}, {}, {}); // Z<{}, string[]> +>x2 : Symbol(x2, Decl(instantiatedTypeAliasDisplay.ts, 14, 5)) +>f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 10, 39)) + diff --git a/tests/baselines/reference/instantiatedTypeAliasDisplay.types b/tests/baselines/reference/instantiatedTypeAliasDisplay.types new file mode 100644 index 00000000000..44885777e74 --- /dev/null +++ b/tests/baselines/reference/instantiatedTypeAliasDisplay.types @@ -0,0 +1,66 @@ +=== tests/cases/compiler/instantiatedTypeAliasDisplay.ts === +// Repros from #12066 + +interface X { +>X : X +>A : A + + a: A; +>a : A +>A : A +} +interface Y { +>Y : Y +>B : B + + b: B; +>b : B +>B : B +} +type Z = X | Y; +>Z : Z +>A : A +>B : B +>X : X +>A : A +>Y : Y +>B : B + +declare function f1(): Z; +>f1 : () => Z +>A : A +>Z : Z +>A : A + +declare function f2(a: A, b: B, c: C, d: D): Z; +>f2 : (a: A, b: B, c: C, d: D) => Z +>A : A +>B : B +>C : C +>D : D +>E : E +>a : A +>A : A +>b : B +>B : B +>c : C +>C : C +>d : D +>D : D +>Z : Z +>A : A + +const x1 = f1(); // Z +>x1 : Z +>f1() : Z +>f1 : () => Z + +const x2 = f2({}, {}, {}, {}); // Z<{}, string[]> +>x2 : Z<{}, string[]> +>f2({}, {}, {}, {}) : Z<{}, string[]> +>f2 : (a: A, b: B, c: C, d: D) => Z +>{} : {} +>{} : {} +>{} : {} +>{} : {} + diff --git a/tests/cases/compiler/instantiatedTypeAliasDisplay.ts b/tests/cases/compiler/instantiatedTypeAliasDisplay.ts new file mode 100644 index 00000000000..d2abaaf8afe --- /dev/null +++ b/tests/cases/compiler/instantiatedTypeAliasDisplay.ts @@ -0,0 +1,15 @@ +// Repros from #12066 + +interface X { + a: A; +} +interface Y { + b: B; +} +type Z = X | Y; + +declare function f1(): Z; +declare function f2(a: A, b: B, c: C, d: D): Z; + +const x1 = f1(); // Z +const x2 = f2({}, {}, {}, {}); // Z<{}, string[]> \ No newline at end of file From 2bf4bad0e16a3e3d4546afe47d8ef4fb837778f4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 6 Nov 2016 16:00:41 -0800 Subject: [PATCH 15/27] Revert incorrect logic from #11392 --- src/compiler/checker.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d0028896baa..1a93909834b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2229,14 +2229,8 @@ namespace ts { // The specified symbol flags need to be reinterpreted as type flags buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); } - else if (!(flags & TypeFormatFlags.InTypeAlias) && ((getObjectFlags(type) & ObjectFlags.Anonymous && !(type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol && + else if (!(flags & TypeFormatFlags.InTypeAlias) && (getObjectFlags(type) & ObjectFlags.Anonymous || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol && isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) { - // We emit inferred type as type-alias at the current localtion if all the following is true - // the input type is has alias symbol that is accessible - // the input type is a union, intersection or anonymous type that is fully instantiated (if not we want to keep dive into) - // e.g.: export type Bar = () => [X, Y]; - // export type Foo = Bar; - // export const y = (x: Foo) => 1 // we want to emit as ...x: () => [any, string]) const typeArguments = type.aliasTypeArguments; writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags); } From cc9daca38d06719612803e90bdf8ca4fcb706b67 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 6 Nov 2016 16:02:32 -0800 Subject: [PATCH 16/27] Accept new baselines --- .../declarationEmitTypeAliasWithTypeParameters1.js | 2 +- .../declarationEmitTypeAliasWithTypeParameters1.types | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters1.js b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters1.js index c41c4690391..6079de35964 100644 --- a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters1.js +++ b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters1.js @@ -12,4 +12,4 @@ exports.y = function (x) { return 1; }; //// [declarationEmitTypeAliasWithTypeParameters1.d.ts] export declare type Bar = () => [X, Y]; export declare type Foo = Bar; -export declare const y: (x: () => [any, string]) => number; +export declare const y: (x: Bar) => number; diff --git a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters1.types b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters1.types index 3ff9f9bde1d..a8b0f146f8e 100644 --- a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters1.types +++ b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters1.types @@ -8,15 +8,15 @@ export type Bar = () => [X, Y]; >Y : Y export type Foo = Bar; ->Foo : () => [any, Y] +>Foo : Bar >Y : Y >Bar : Bar >Y : Y export const y = (x: Foo) => 1 ->y : (x: () => [any, string]) => number ->(x: Foo) => 1 : (x: () => [any, string]) => number ->x : () => [any, string] ->Foo : () => [any, Y] +>y : (x: Bar) => number +>(x: Foo) => 1 : (x: Bar) => number +>x : Bar +>Foo : Bar >1 : 1 From d5c67312f619f3283c2c1a448b965d6698da41a5 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 7 Nov 2016 12:41:22 -0800 Subject: [PATCH 17/27] Add `realpath` implementation for lshost --- src/server/lsHost.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/server/lsHost.ts b/src/server/lsHost.ts index 628de71bb7a..f1e80d95880 100644 --- a/src/server/lsHost.ts +++ b/src/server/lsHost.ts @@ -13,6 +13,7 @@ namespace ts.server { private readonly resolveModuleName: typeof resolveModuleName; readonly trace: (s: string) => void; + readonly realpath?: (path: string) => string; constructor(private readonly host: ServerHost, private readonly project: Project, private readonly cancellationToken: HostCancellationToken) { this.getCanonicalFileName = ts.createGetCanonicalFileName(this.host.useCaseSensitiveFileNames); @@ -39,6 +40,10 @@ namespace ts.server { } return primaryResult; }; + + if (this.host.realpath) { + this.realpath = path => this.host.realpath(path); + } } public startRecordingFilesWithChangedResolutions() { From 4ffdea838a65cf948f4ace6e659fc7936c7ea9a7 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 7 Nov 2016 13:36:08 -0800 Subject: [PATCH 18/27] Ports #12051 and #12032 into master (#12090) * use local registry to check if typings package exist (#12014) use local registry to check if typings package exist * enable sending telemetry events to tsserver client (#12035) enable sending telemetry events --- Jakefile.js | 2 + .../unittests/tsserverProjectSystem.ts | 33 +-- src/harness/unittests/typingsInstaller.ts | 261 ++++++++++-------- src/server/editorServices.ts | 4 +- src/server/protocol.ts | 26 ++ src/server/server.ts | 77 ++++-- src/server/session.ts | 6 +- src/server/shared.ts | 24 ++ src/server/tsconfig.json | 1 + src/server/tsconfig.library.json | 1 + src/server/types.d.ts | 26 +- .../typingsInstaller/nodeTypingsInstaller.ts | 141 +++++----- src/server/typingsInstaller/tsconfig.json | 1 + .../typingsInstaller/typingsInstaller.ts | 135 ++++----- src/server/utilities.ts | 2 + 15 files changed, 415 insertions(+), 325 deletions(-) create mode 100644 src/server/shared.ts diff --git a/Jakefile.js b/Jakefile.js index 8ce70eb353f..fc2b6359355 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -171,6 +171,7 @@ var servicesSources = [ var serverCoreSources = [ "types.d.ts", + "shared.ts", "utilities.ts", "scriptVersionCache.ts", "typingsCache.ts", @@ -193,6 +194,7 @@ var cancellationTokenSources = [ var typingsInstallerSources = [ "../types.d.ts", + "../shared.ts", "typingsInstaller.ts", "nodeTypingsInstaller.ts" ].map(function (f) { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 15cfa3f8c8e..ee6139b1215 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -18,7 +18,6 @@ namespace ts.projectSystem { }; export interface PostExecAction { - readonly requestKind: TI.RequestKind; readonly success: boolean; readonly callback: TI.RequestCompletedAction; } @@ -47,9 +46,14 @@ namespace ts.projectSystem { export class TestTypingsInstaller extends TI.TypingsInstaller implements server.ITypingsInstaller { protected projectService: server.ProjectService; - constructor(readonly globalTypingsCacheLocation: string, throttleLimit: number, readonly installTypingHost: server.ServerHost, log?: TI.Log) { - super(globalTypingsCacheLocation, safeList.path, throttleLimit, log); - this.init(); + constructor( + readonly globalTypingsCacheLocation: string, + throttleLimit: number, + installTypingHost: server.ServerHost, + readonly typesRegistry = createMap(), + telemetryEnabled?: boolean, + log?: TI.Log) { + super(installTypingHost, globalTypingsCacheLocation, safeList.path, throttleLimit, telemetryEnabled, log); } safeFileList = safeList.path; @@ -63,9 +67,8 @@ namespace ts.projectSystem { } } - checkPendingCommands(expected: TI.RequestKind[]) { - assert.equal(this.postExecActions.length, expected.length, `Expected ${expected.length} post install actions`); - this.postExecActions.forEach((act, i) => assert.equal(act.requestKind, expected[i], "Unexpected post install action")); + checkPendingCommands(expectedCount: number) { + assert.equal(this.postExecActions.length, expectedCount, `Expected ${expectedCount} post install actions`); } onProjectClosed() { @@ -79,15 +82,8 @@ namespace ts.projectSystem { return this.installTypingHost; } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { - switch (requestKind) { - case TI.NpmViewRequest: - case TI.NpmInstallRequest: - break; - default: - assert.isTrue(false, `request ${requestKind} is not supported`); - } - this.addPostExecAction(requestKind, "success", cb); + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { + this.addPostExecAction("success", cb); } sendResponse(response: server.SetTypings | server.InvalidateCachedTypings) { @@ -99,12 +95,11 @@ namespace ts.projectSystem { this.install(request); } - addPostExecAction(requestKind: TI.RequestKind, stdout: string | string[], cb: TI.RequestCompletedAction) { + addPostExecAction(stdout: string | string[], cb: TI.RequestCompletedAction) { const out = typeof stdout === "string" ? stdout : createNpmPackageJsonString(stdout); const action: PostExecAction = { success: !!out, - callback: cb, - requestKind + callback: cb }; this.postExecActions.push(action); } diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 356992d5717..2dda506ad58 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -8,44 +8,44 @@ namespace ts.projectSystem { interface InstallerParams { globalTypingsCacheLocation?: string; throttleLimit?: number; + typesRegistry?: Map; + } + + function createTypesRegistry(...list: string[]): Map { + const map = createMap(); + for (const l of list) { + map[l] = undefined; + } + return map; } class Installer extends TestTypingsInstaller { - constructor(host: server.ServerHost, p?: InstallerParams, log?: TI.Log) { + constructor(host: server.ServerHost, p?: InstallerParams, telemetryEnabled?: boolean, log?: TI.Log) { super( (p && p.globalTypingsCacheLocation) || "/a/data", (p && p.throttleLimit) || 5, host, + (p && p.typesRegistry), + telemetryEnabled, log); } - installAll(expectedView: typeof TI.NpmViewRequest[], expectedInstall: typeof TI.NpmInstallRequest[]) { - this.checkPendingCommands(expectedView); - this.executePendingCommands(); - this.checkPendingCommands(expectedInstall); + installAll(expectedCount: number) { + this.checkPendingCommands(expectedCount); this.executePendingCommands(); } } - describe("typingsInstaller", () => { - function executeCommand(self: Installer, host: TestServerHost, installedTypings: string[], typingFiles: FileOrFolder[], requestKind: TI.RequestKind, cb: TI.RequestCompletedAction): void { - switch (requestKind) { - case TI.NpmInstallRequest: - self.addPostExecAction(requestKind, installedTypings, success => { - for (const file of typingFiles) { - host.createFileOrFolder(file, /*createParentDirectory*/ true); - } - cb(success); - }); - break; - case TI.NpmViewRequest: - self.addPostExecAction(requestKind, installedTypings, cb); - break; - default: - assert.isTrue(false, `unexpected request kind ${requestKind}`); - break; + function executeCommand(self: Installer, host: TestServerHost, installedTypings: string[], typingFiles: FileOrFolder[], cb: TI.RequestCompletedAction): void { + self.addPostExecAction(installedTypings, success => { + for (const file of typingFiles) { + host.createFileOrFolder(file, /*createParentDirectory*/ true); } - } + cb(success); + }); + } + + describe("typingsInstaller", () => { it("configured projects (typings installed) 1", () => { const file1 = { path: "/a/b/app.js", @@ -79,12 +79,12 @@ namespace ts.projectSystem { const host = createServerHost([file1, tsconfig, packageJson]); const installer = new (class extends Installer { constructor() { - super(host); + super(host, { typesRegistry: createTypesRegistry("jquery") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jquery]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -95,7 +95,7 @@ namespace ts.projectSystem { const p = projectService.configuredProjects[0]; checkProjectActualFiles(p, [file1.path]); - installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + installer.installAll(/*expectedCount*/ 1); checkNumberOfProjects(projectService, { configuredProjects: 1 }); checkProjectActualFiles(p, [file1.path, jquery.path]); @@ -123,12 +123,12 @@ namespace ts.projectSystem { const host = createServerHost([file1, packageJson]); const installer = new (class extends Installer { constructor() { - super(host); + super(host, { typesRegistry: createTypesRegistry("jquery") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jquery]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -139,7 +139,7 @@ namespace ts.projectSystem { const p = projectService.inferredProjects[0]; checkProjectActualFiles(p, [file1.path]); - installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + installer.installAll(/*expectedCount*/ 1); checkNumberOfProjects(projectService, { inferredProjects: 1 }); checkProjectActualFiles(p, [file1.path, jquery.path]); @@ -167,7 +167,7 @@ namespace ts.projectSystem { options: {}, rootFiles: [toExternalFile(file1.path)] }); - installer.checkPendingCommands([]); + installer.checkPendingCommands(/*expectedCount*/ 0); // by default auto discovery will kick in if project contain only .js/.d.ts files // in this case project contain only ts files - no auto discovery projectService.checkNumberOfProjects({ externalProjects: 1 }); @@ -181,7 +181,7 @@ namespace ts.projectSystem { const host = createServerHost([file1]); const installer = new (class extends Installer { constructor() { - super(host); + super(host, { typesRegistry: createTypesRegistry("jquery") }); } enqueueInstallTypingsRequest() { assert(false, "auto discovery should not be enabled"); @@ -196,7 +196,7 @@ namespace ts.projectSystem { rootFiles: [toExternalFile(file1.path)], typingOptions: { include: ["jquery"] } }); - installer.checkPendingCommands([]); + installer.checkPendingCommands(/*expectedCount*/ 0); // by default auto discovery will kick in if project contain only .js/.d.ts files // in this case project contain only ts files - no auto discovery even if typing options is set projectService.checkNumberOfProjects({ externalProjects: 1 }); @@ -215,16 +215,16 @@ namespace ts.projectSystem { let enqueueIsCalled = false; const installer = new (class extends Installer { constructor() { - super(host); + super(host, { typesRegistry: createTypesRegistry("jquery") }); } enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray) { enqueueIsCalled = true; super.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { - const installedTypings = ["@types/jquery"]; + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { + const installedTypings = ["@types/node"]; const typingFiles = [jquery]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -234,11 +234,11 @@ namespace ts.projectSystem { projectFileName, options: {}, rootFiles: [toExternalFile(file1.path)], - typingOptions: { enableAutoDiscovery: true, include: ["node"] } + typingOptions: { enableAutoDiscovery: true, include: ["jquery"] } }); assert.isTrue(enqueueIsCalled, "expected enqueueIsCalled to be true"); - installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + installer.installAll(/*expectedCount*/ 1); // autoDiscovery is set in typing options - use it even if project contains only .ts files projectService.checkNumberOfProjects({ externalProjects: 1 }); @@ -273,12 +273,12 @@ namespace ts.projectSystem { const host = createServerHost([file1, file2, file3]); const installer = new (class extends Installer { constructor() { - super(host); + super(host, { typesRegistry: createTypesRegistry("lodash", "react") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { const installedTypings = ["@types/lodash", "@types/react"]; const typingFiles = [lodash, react]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -295,7 +295,7 @@ namespace ts.projectSystem { projectService.checkNumberOfProjects({ externalProjects: 1 }); checkProjectActualFiles(p, [file1.path, file2.path, file3.path]); - installer.installAll([TI.NpmViewRequest, TI.NpmViewRequest], [TI.NpmInstallRequest], ); + installer.installAll(/*expectedCount*/ 1); checkNumberOfProjects(projectService, { externalProjects: 1 }); checkProjectActualFiles(p, [file1.path, file2.path, file3.path, lodash.path, react.path]); @@ -317,16 +317,16 @@ namespace ts.projectSystem { let enqueueIsCalled = false; const installer = new (class extends Installer { constructor() { - super(host); + super(host, { typesRegistry: createTypesRegistry("jquery") }); } enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray) { enqueueIsCalled = true; super.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { const installedTypings: string[] = []; const typingFiles: FileOrFolder[] = []; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -343,7 +343,7 @@ namespace ts.projectSystem { projectService.checkNumberOfProjects({ externalProjects: 1 }); checkProjectActualFiles(p, [file1.path, file2.path]); - installer.checkPendingCommands([]); + installer.checkPendingCommands(/*expectedCount*/ 0); checkNumberOfProjects(projectService, { externalProjects: 1 }); checkProjectActualFiles(p, [file1.path, file2.path]); @@ -396,12 +396,12 @@ namespace ts.projectSystem { const host = createServerHost([file1, file2, file3, packageJson]); const installer = new (class extends Installer { constructor() { - super(host); + super(host, { typesRegistry: createTypesRegistry("jquery", "commander", "moment", "express") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { const installedTypings = ["@types/commander", "@types/express", "@types/jquery", "@types/moment"]; const typingFiles = [commander, express, jquery, moment]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -418,10 +418,7 @@ namespace ts.projectSystem { projectService.checkNumberOfProjects({ externalProjects: 1 }); checkProjectActualFiles(p, [file1.path, file2.path, file3.path]); - installer.installAll( - [TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest], - [TI.NpmInstallRequest] - ); + installer.installAll(/*expectedCount*/ 1); checkNumberOfProjects(projectService, { externalProjects: 1 }); checkProjectActualFiles(p, [file1.path, file2.path, file3.path, commander.path, express.path, jquery.path, moment.path]); @@ -475,11 +472,11 @@ namespace ts.projectSystem { const host = createServerHost([lodashJs, commanderJs, file3, packageJson]); const installer = new (class extends Installer { constructor() { - super(host, { throttleLimit: 3 }); + super(host, { throttleLimit: 3, typesRegistry: createTypesRegistry("commander", "express", "jquery", "moment", "lodash") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { const installedTypings = ["@types/commander", "@types/express", "@types/jquery", "@types/moment", "@types/lodash"]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -495,18 +492,7 @@ namespace ts.projectSystem { const p = projectService.externalProjects[0]; projectService.checkNumberOfProjects({ externalProjects: 1 }); checkProjectActualFiles(p, [lodashJs.path, commanderJs.path, file3.path]); - // expected 3 view requests in the queue - installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest]); - assert.equal(installer.pendingRunRequests.length, 2, "expected 2 pending requests"); - - // push view requests - installer.executePendingCommands(); - // expected 2 remaining view requests in the queue - installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest]); - // push view requests - installer.executePendingCommands(); - // expected one install request - installer.checkPendingCommands([TI.NpmInstallRequest]); + installer.checkPendingCommands(/*expectedCount*/ 1); installer.executePendingCommands(); // expected all typings file to exist for (const f of typingFiles) { @@ -565,22 +551,17 @@ namespace ts.projectSystem { const host = createServerHost([lodashJs, commanderJs, file3]); const installer = new (class extends Installer { constructor() { - super(host, { throttleLimit: 3 }); + super(host, { throttleLimit: 1, typesRegistry: createTypesRegistry("commander", "jquery", "lodash", "cordova", "gulp", "grunt") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { - if (requestKind === TI.NpmInstallRequest) { - let typingFiles: (FileOrFolder & { typings: string })[] = []; - if (args.indexOf("@types/commander") >= 0) { - typingFiles = [commander, jquery, lodash, cordova]; - } - else { - typingFiles = [grunt, gulp]; - } - executeCommand(this, host, typingFiles.map(f => f.typings), typingFiles, requestKind, cb); + installWorker(_requestId: number, args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { + let typingFiles: (FileOrFolder & { typings: string })[] = []; + if (args.indexOf("@types/commander") >= 0) { + typingFiles = [commander, jquery, lodash, cordova]; } else { - executeCommand(this, host, [], [], requestKind, cb); + typingFiles = [grunt, gulp]; } + executeCommand(this, host, typingFiles.map(f => f.typings), typingFiles, cb); } })(); @@ -594,8 +575,8 @@ namespace ts.projectSystem { typingOptions: { include: ["jquery", "cordova"] } }); - installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest]); - assert.equal(installer.pendingRunRequests.length, 1, "expect one throttled request"); + installer.checkPendingCommands(/*expectedCount*/ 1); + assert.equal(installer.pendingRunRequests.length, 0, "expect no throttled requests"); // Create project #2 with 2 typings const projectFileName2 = "/a/app/test2.csproj"; @@ -605,7 +586,7 @@ namespace ts.projectSystem { rootFiles: [toExternalFile(file3.path)], typingOptions: { include: ["grunt", "gulp"] } }); - assert.equal(installer.pendingRunRequests.length, 3, "expect three throttled request"); + assert.equal(installer.pendingRunRequests.length, 1, "expect one throttled request"); const p1 = projectService.externalProjects[0]; const p2 = projectService.externalProjects[1]; @@ -613,18 +594,14 @@ namespace ts.projectSystem { checkProjectActualFiles(p1, [lodashJs.path, commanderJs.path, file3.path]); checkProjectActualFiles(p2, [file3.path]); - installer.executePendingCommands(); - // expected one view request from the first project and two - from the second one - installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest]); + + // expected one install request from the second project + installer.checkPendingCommands(/*expectedCount*/ 1); assert.equal(installer.pendingRunRequests.length, 0, "expected no throttled requests"); installer.executePendingCommands(); - // should be two install requests from both projects - installer.checkPendingCommands([TI.NpmInstallRequest, TI.NpmInstallRequest]); - installer.executePendingCommands(); - checkProjectActualFiles(p1, [lodashJs.path, commanderJs.path, file3.path, commander.path, jquery.path, lodash.path, cordova.path]); checkProjectActualFiles(p2, [file3.path, grunt.path, gulp.path]); }); @@ -653,12 +630,12 @@ namespace ts.projectSystem { const host = createServerHost([app, jsconfig, jquery, jqueryPackage]); const installer = new (class extends Installer { constructor() { - super(host, { globalTypingsCacheLocation: "/tmp" }); + super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jqueryDTS]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -669,7 +646,7 @@ namespace ts.projectSystem { const p = projectService.configuredProjects[0]; checkProjectActualFiles(p, [app.path]); - installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + installer.installAll(/*expectedCount*/ 1); checkNumberOfProjects(projectService, { configuredProjects: 1 }); checkProjectActualFiles(p, [app.path, jqueryDTS.path]); @@ -699,12 +676,12 @@ namespace ts.projectSystem { const host = createServerHost([app, jsconfig, bowerJson]); const installer = new (class extends Installer { constructor() { - super(host, { globalTypingsCacheLocation: "/tmp" }); + super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jqueryDTS]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -715,7 +692,7 @@ namespace ts.projectSystem { const p = projectService.configuredProjects[0]; checkProjectActualFiles(p, [app.path]); - installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + installer.installAll(/*expectedCount*/ 1); checkNumberOfProjects(projectService, { configuredProjects: 1 }); checkProjectActualFiles(p, [app.path, jqueryDTS.path]); @@ -742,23 +719,23 @@ namespace ts.projectSystem { const host = createServerHost([f, brokenPackageJson]); const installer = new (class extends Installer { constructor() { - super(host, { globalTypingsCacheLocation: cachePath }); + super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { const installedTypings = ["@types/commander"]; const typingFiles = [commander]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); const service = createProjectService(host, { typingsInstaller: installer }); service.openClientFile(f.path); - installer.checkPendingCommands([]); + installer.checkPendingCommands(/*expectedCount*/ 0); host.reloadFS([f, fixedPackageJson]); host.triggerFileWatcherCallback(fixedPackageJson.path, /*removed*/ false); - // expected one view and one install request - installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + // expected install request + installer.installAll(/*expectedCount*/ 1); service.checkNumberOfProjects({ inferredProjects: 1 }); checkProjectActualFiles(service.inferredProjects[0], [f.path, commander.path]); @@ -783,12 +760,12 @@ namespace ts.projectSystem { const host = createServerHost([file]); const installer = new (class extends Installer { constructor() { - super(host, { globalTypingsCacheLocation: cachePath }); + super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("node", "commander") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { const installedTypings = ["@types/node", "@types/commander"]; const typingFiles = [node, commander]; - executeCommand(this, host, installedTypings, typingFiles, requestKind, cb); + executeCommand(this, host, installedTypings, typingFiles, cb); } })(); const service = createProjectService(host, { typingsInstaller: installer }); @@ -797,7 +774,7 @@ namespace ts.projectSystem { service.checkNumberOfProjects({ inferredProjects: 1 }); checkProjectActualFiles(service.inferredProjects[0], [file.path]); - installer.installAll([TI.NpmViewRequest, TI.NpmViewRequest], [TI.NpmInstallRequest]); + installer.installAll(/*expectedCount*/1); assert.isTrue(host.fileExists(node.path), "typings for 'node' should be created"); assert.isTrue(host.fileExists(commander.path), "typings for 'commander' should be created"); @@ -822,14 +799,10 @@ namespace ts.projectSystem { const host = createServerHost([f1]); const installer = new (class extends Installer { constructor() { - super(host, { globalTypingsCacheLocation: "/tmp" }); + super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("foo") }); } - executeRequest(requestKind: TI.RequestKind, _requestId: number, args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { - if (requestKind === TI.NpmViewRequest) { - // args should have only non-scoped packages - scoped packages are not yet supported - assert.deepEqual(args, ["foo"]); - } - executeCommand(this, host, ["foo"], [], requestKind, cb); + installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + executeCommand(this, host, ["foo"], [], cb); } })(); const projectService = createProjectService(host, { typingsInstaller: installer }); @@ -844,7 +817,7 @@ namespace ts.projectSystem { ["foo", "foo", "foo", "@bar/router", "@bar/common", "@bar/common"] ); - installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]); + installer.installAll(/*expectedCount*/ 1); }); it("cached unresolved typings are not recomputed if program structure did not change", () => { @@ -934,16 +907,16 @@ namespace ts.projectSystem { const host = createServerHost([f1, packageJson]); const installer = new (class extends Installer { constructor() { - super(host, { globalTypingsCacheLocation: "/tmp" }, { isEnabled: () => true, writeLine: msg => messages.push(msg) }); + super(host, { globalTypingsCacheLocation: "/tmp" }, /*telemetryEnabled*/ false, { isEnabled: () => true, writeLine: msg => messages.push(msg) }); } - executeRequest() { + installWorker(_requestId: number, _args: string[], _cwd: string, _cb: server.typingsInstaller.RequestCompletedAction) { assert(false, "runCommand should not be invoked"); } })(); const projectService = createProjectService(host, { typingsInstaller: installer }); projectService.openClientFile(f1.path); - installer.checkPendingCommands([]); + installer.checkPendingCommands(/*expectedCount*/ 0); assert.isTrue(messages.indexOf("Package name '; say ‘Hello from TypeScript!’ #' contains non URI safe characters") > 0, "should find package with invalid name"); }); }); @@ -978,4 +951,50 @@ namespace ts.projectSystem { assert.deepEqual(result.newTypingNames, ["bar"]); }); }); + + describe("telemetry events", () => { + it ("should be received", () => { + const f1 = { + path: "/a/app.js", + content: "" + }; + const package = { + path: "/a/package.json", + content: JSON.stringify({ dependencies: { "commander": "1.0.0" } }) + }; + const cachePath = "/a/cache/"; + const commander = { + path: cachePath + "node_modules/@types/commander/index.d.ts", + content: "export let x: number" + }; + const host = createServerHost([f1, package]); + let seenTelemetryEvent = false; + const installer = new (class extends Installer { + constructor() { + super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }, /*telemetryEnabled*/ true); + } + installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + const installedTypings = ["@types/commander"]; + const typingFiles = [commander]; + executeCommand(this, host, installedTypings, typingFiles, cb); + } + sendResponse(response: server.SetTypings | server.InvalidateCachedTypings | server.TypingsInstallEvent) { + if (response.kind === server.EventInstall) { + assert.deepEqual(response.packagesToInstall, ["@types/commander"]); + seenTelemetryEvent = true; + return; + } + super.sendResponse(response); + } + })(); + const projectService = createProjectService(host, { typingsInstaller: installer }); + projectService.openClientFile(f1.path); + + installer.installAll(/*expectedCount*/ 1); + + assert.isTrue(seenTelemetryEvent); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkProjectActualFiles(projectService.inferredProjects[0], [f1.path, commander.path]); + }); + }); } \ No newline at end of file diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index a02becd87c4..bf760106b74 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -286,10 +286,10 @@ namespace ts.server { return; } switch (response.kind) { - case "set": + case ActionSet: this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.unresolvedImports, response.typings); break; - case "invalidate": + case ActionInvalidate: this.typingsCache.deleteTypingsForProject(response.projectName); break; } diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 7da95e49575..d13caf7f01b 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2057,6 +2057,32 @@ namespace ts.server.protocol { childItems?: NavigationTree[]; } + export type TelemetryEventName = "telemetry"; + + export interface TelemetryEvent extends Event { + event: TelemetryEventName; + body: TelemetryEventBody; + } + + export interface TelemetryEventBody { + telemetryEventName: string; + payload: any; + } + + export type TypingsInstalledTelemetryEventName = "typingsInstalled"; + + export interface TypingsInstalledTelemetryEventBody extends TelemetryEventBody { + telemetryEventName: TypingsInstalledTelemetryEventName; + payload: TypingsInstalledTelemetryEventPayload; + } + + export interface TypingsInstalledTelemetryEventPayload { + /** + * Comma separated list of installed typing packages + */ + installedPackages: string; + } + export interface NavBarResponse extends Response { body?: NavigationBarItem[]; } diff --git a/src/server/server.ts b/src/server/server.ts index 5057a13dbd1..3b33554aaba 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -1,4 +1,5 @@ /// +/// /// // used in fs.writeSync /* tslint:disable:no-null-keyword */ @@ -196,8 +197,10 @@ namespace ts.server { private socket: NodeSocket; private projectService: ProjectService; private throttledOperations: ThrottledOperations; + private telemetrySender: EventSender; constructor( + private readonly telemetryEnabled: boolean, private readonly logger: server.Logger, host: ServerHost, eventPort: number, @@ -226,15 +229,22 @@ namespace ts.server { this.socket.write(formatMessage({ seq, type: "event", event, body }, this.logger, Buffer.byteLength, this.newLine), "utf8"); } + setTelemetrySender(telemetrySender: EventSender) { + this.telemetrySender = telemetrySender; + } + attach(projectService: ProjectService) { this.projectService = projectService; if (this.logger.hasLevel(LogLevel.requestTime)) { this.logger.info("Binding..."); } - const args: string[] = ["--globalTypingsCacheLocation", this.globalTypingsCacheLocation]; + const args: string[] = [Arguments.GlobalCacheLocation, this.globalTypingsCacheLocation]; + if (this.telemetryEnabled) { + args.push(Arguments.EnableTelemetry); + } if (this.logger.loggingEnabled() && this.logger.getLogFileName()) { - args.push("--logFile", combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName())), `ti-${process.pid}.log`)); + args.push(Arguments.LogFile, combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName())), `ti-${process.pid}.log`)); } const execArgv: string[] = []; { @@ -280,12 +290,25 @@ namespace ts.server { }); } - private handleMessage(response: SetTypings | InvalidateCachedTypings) { + private handleMessage(response: SetTypings | InvalidateCachedTypings | TypingsInstallEvent) { if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Received response: ${JSON.stringify(response)}`); } + if (response.kind === EventInstall) { + if (this.telemetrySender) { + const body: protocol.TypingsInstalledTelemetryEventBody = { + telemetryEventName: "typingsInstalled", + payload: { + installedPackages: response.packagesToInstall.join(",") + } + }; + const eventName: protocol.TelemetryEventName = "telemetry"; + this.telemetrySender.event(body, eventName); + } + return; + } this.projectService.updateTypingsForProject(response); - if (response.kind == "set" && this.socket) { + if (response.kind == ActionSet && this.socket) { this.sendEvent(0, "setTypings", response); } } @@ -300,18 +323,25 @@ namespace ts.server { useSingleInferredProject: boolean, disableAutomaticTypingAcquisition: boolean, globalTypingsCacheLocation: string, + telemetryEnabled: boolean, logger: server.Logger) { - super( - host, - cancellationToken, - useSingleInferredProject, - disableAutomaticTypingAcquisition - ? nullTypingsInstaller - : new NodeTypingsInstaller(logger, host, installerEventPort, globalTypingsCacheLocation, host.newLine), - Buffer.byteLength, - process.hrtime, - logger, - canUseEvents); + const typingsInstaller = disableAutomaticTypingAcquisition + ? undefined + : new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, host.newLine); + + super( + host, + cancellationToken, + useSingleInferredProject, + typingsInstaller || nullTypingsInstaller, + Buffer.byteLength, + process.hrtime, + logger, + canUseEvents); + + if (telemetryEnabled && typingsInstaller) { + typingsInstaller.setTelemetrySender(this); + } } exit() { @@ -538,17 +568,17 @@ namespace ts.server { let eventPort: number; { - const index = sys.args.indexOf("--eventPort"); - if (index >= 0 && index < sys.args.length - 1) { - const v = parseInt(sys.args[index + 1]); - if (!isNaN(v)) { - eventPort = v; - } + const str = findArgument("--eventPort"); + const v = str && parseInt(str); + if (!isNaN(v)) { + eventPort = v; } } - const useSingleInferredProject = sys.args.indexOf("--useSingleInferredProject") >= 0; - const disableAutomaticTypingAcquisition = sys.args.indexOf("--disableAutomaticTypingAcquisition") >= 0; + const useSingleInferredProject = hasArgument("--useSingleInferredProject"); + const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition"); + const telemetryEnabled = hasArgument(Arguments.EnableTelemetry); + const ioSession = new IOSession( sys, cancellationToken, @@ -557,6 +587,7 @@ namespace ts.server { useSingleInferredProject, disableAutomaticTypingAcquisition, getGlobalTypingsCacheLocation(), + telemetryEnabled, logger); process.on("uncaughtException", function (err: Error) { ioSession.logError(err, "unknown"); diff --git a/src/server/session.ts b/src/server/session.ts index 545701f1449..b250393b7ff 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -73,6 +73,10 @@ namespace ts.server { project: Project; } + export interface EventSender { + event(payload: any, eventName: string): void; + } + function allEditsBeforePos(edits: ts.TextChange[], pos: number) { for (const edit of edits) { if (textSpanEnd(edit.span) >= pos) { @@ -165,7 +169,7 @@ namespace ts.server { return `Content-Length: ${1 + len}\r\n\r\n${json}${newLine}`; } - export class Session { + export class Session implements EventSender { private readonly gcTimer: GcTimer; protected projectService: ProjectService; private errorTimer: any; /*NodeJS.Timer | number*/ diff --git a/src/server/shared.ts b/src/server/shared.ts new file mode 100644 index 00000000000..81a1f7fb55b --- /dev/null +++ b/src/server/shared.ts @@ -0,0 +1,24 @@ +/// + +namespace ts.server { + export const ActionSet: ActionSet = "action::set"; + export const ActionInvalidate: ActionInvalidate = "action::invalidate"; + export const EventInstall: EventInstall = "event::install"; + + export namespace Arguments { + export const GlobalCacheLocation = "--globalTypingsCacheLocation"; + export const LogFile = "--logFile"; + export const EnableTelemetry = "--enableTelemetry"; + } + + export function hasArgument(argumentName: string) { + return sys.args.indexOf(argumentName) >= 0; + } + + export function findArgument(argumentName: string) { + const index = sys.args.indexOf(argumentName); + return index >= 0 && index < sys.args.length - 1 + ? sys.args[index + 1] + : undefined; + } +} \ No newline at end of file diff --git a/src/server/tsconfig.json b/src/server/tsconfig.json index a99994d97c5..85c88679164 100644 --- a/src/server/tsconfig.json +++ b/src/server/tsconfig.json @@ -18,6 +18,7 @@ "files": [ "../services/shims.ts", "../services/utilities.ts", + "shared.ts", "utilities.ts", "scriptVersionCache.ts", "scriptInfo.ts", diff --git a/src/server/tsconfig.library.json b/src/server/tsconfig.library.json index e269629b558..5483cc8ec28 100644 --- a/src/server/tsconfig.library.json +++ b/src/server/tsconfig.library.json @@ -15,6 +15,7 @@ "files": [ "../services/shims.ts", "../services/utilities.ts", + "shared.ts", "utilities.ts", "scriptVersionCache.ts", "scriptInfo.ts", diff --git a/src/server/types.d.ts b/src/server/types.d.ts index ec2befe8fa9..95f9519cc38 100644 --- a/src/server/types.d.ts +++ b/src/server/types.d.ts @@ -41,23 +41,33 @@ declare namespace ts.server { readonly kind: "closeProject"; } - export type SetRequest = "set"; - export type InvalidateRequest = "invalidate"; + export type ActionSet = "action::set"; + export type ActionInvalidate = "action::invalidate"; + export type EventInstall = "event::install"; + export interface TypingInstallerResponse { - readonly projectName: string; - readonly kind: SetRequest | InvalidateRequest; + readonly kind: ActionSet | ActionInvalidate | EventInstall; } - export interface SetTypings extends TypingInstallerResponse { + export interface ProjectResponse extends TypingInstallerResponse { + readonly projectName: string; + } + + export interface SetTypings extends ProjectResponse { readonly typingOptions: ts.TypingOptions; readonly compilerOptions: ts.CompilerOptions; readonly typings: string[]; readonly unresolvedImports: SortedReadonlyArray; - readonly kind: SetRequest; + readonly kind: ActionSet; } - export interface InvalidateCachedTypings extends TypingInstallerResponse { - readonly kind: InvalidateRequest; + export interface InvalidateCachedTypings extends ProjectResponse { + readonly kind: ActionInvalidate; + } + + export interface TypingsInstallEvent extends TypingInstallerResponse { + readonly packagesToInstall: ReadonlyArray; + readonly kind: EventInstall; } export interface InstallTypingHost extends JsTyping.TypingResolutionHost { diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 89419264930..7020b6aa4f8 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -33,42 +33,81 @@ namespace ts.server.typingsInstaller { } } - type HttpGet = { - (url: string, callback: (response: HttpResponse) => void): NodeJS.EventEmitter; - }; - - interface HttpResponse extends NodeJS.ReadableStream { - statusCode: number; - statusMessage: string; - destroy(): void; + interface TypesRegistryFile { + entries: MapLike; } + function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypingHost, log: Log): Map { + if (!host.fileExists(typesRegistryFilePath)) { + if (log.isEnabled()) { + log.writeLine(`Types registry file '${typesRegistryFilePath}' does not exist`); + } + return createMap(); + } + try { + const content = JSON.parse(host.readFile(typesRegistryFilePath)); + return createMap(content.entries); + } + catch (e) { + if (log.isEnabled()) { + log.writeLine(`Error when loading types registry file '${typesRegistryFilePath}': ${(e).message}, ${(e).stack}`); + } + return createMap(); + } + } + + const TypesRegistryPackageName = "types-registry"; + function getTypesRegistryFileLocation(globalTypingsCacheLocation: string): string { + return combinePaths(normalizeSlashes(globalTypingsCacheLocation), `node_modules/${TypesRegistryPackageName}/index.json`); + } + + type Exec = { (command: string, options: { cwd: string }, callback?: (error: Error, stdout: string, stderr: string) => void): any }; + type ExecSync = { + (command: string, options: { cwd: string, stdio: "ignore" }): any + }; + export class NodeTypingsInstaller extends TypingsInstaller { private readonly exec: Exec; - private readonly httpGet: HttpGet; private readonly npmPath: string; - readonly installTypingHost: InstallTypingHost = sys; + readonly typesRegistry: Map; - constructor(globalTypingsCacheLocation: string, throttleLimit: number, log: Log) { + constructor(globalTypingsCacheLocation: string, throttleLimit: number, telemetryEnabled: boolean, log: Log) { super( + sys, globalTypingsCacheLocation, toPath("typingSafeList.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), throttleLimit, + telemetryEnabled, log); if (this.log.isEnabled()) { this.log.writeLine(`Process id: ${process.pid}`); } this.npmPath = getNPMLocation(process.argv[0]); - this.exec = require("child_process").exec; - this.httpGet = require("http").get; + let execSync: ExecSync; + ({ exec: this.exec, execSync } = require("child_process")); + + this.ensurePackageDirectoryExists(globalTypingsCacheLocation); + + try { + if (this.log.isEnabled()) { + this.log.writeLine(`Updating ${TypesRegistryPackageName} npm package...`); + } + execSync(`${this.npmPath} install ${TypesRegistryPackageName}`, { cwd: globalTypingsCacheLocation, stdio: "ignore" }); + } + catch (e) { + if (this.log.isEnabled()) { + this.log.writeLine(`Error updating ${TypesRegistryPackageName} package: ${(e).message}`); + } + } + + this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), this.installTypingHost, this.log); } - init() { - super.init(); + listen() { process.on("message", (req: DiscoverTypings | CloseProject) => { switch (req.kind) { case "discover": @@ -90,66 +129,26 @@ namespace ts.server.typingsInstaller { } } - protected executeRequest(requestKind: RequestKind, requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { + protected installWorker(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { if (this.log.isEnabled()) { - this.log.writeLine(`#${requestId} executing ${requestKind}, arguments'${JSON.stringify(args)}'.`); - } - switch (requestKind) { - case NpmViewRequest: { - // const command = `${self.npmPath} view @types/${typing} --silent name`; - // use http request to global npm registry instead of running npm view - Debug.assert(args.length === 1); - const url = `http://registry.npmjs.org/@types%2f${args[0]}`; - const start = Date.now(); - this.httpGet(url, response => { - let ok = false; - if (this.log.isEnabled()) { - this.log.writeLine(`${requestKind} #${requestId} request to ${url}:: status code ${response.statusCode}, status message '${response.statusMessage}', took ${Date.now() - start} ms`); - } - switch (response.statusCode) { - case 200: // OK - case 301: // redirect - Moved - treat package as present - case 302: // redirect - Found - treat package as present - ok = true; - break; - } - response.destroy(); - onRequestCompleted(ok); - }).on("error", (err: Error) => { - if (this.log.isEnabled()) { - this.log.writeLine(`${requestKind} #${requestId} query to npm registry failed with error ${err.message}, stack ${err.stack}`); - } - onRequestCompleted(/*success*/ false); - }); - } - break; - case NpmInstallRequest: { - const command = `${this.npmPath} install ${args.join(" ")} --save-dev`; - const start = Date.now(); - this.exec(command, { cwd }, (_err, stdout, stderr) => { - if (this.log.isEnabled()) { - this.log.writeLine(`${requestKind} #${requestId} took: ${Date.now() - start} ms${sys.newLine}stdout: ${stdout}${sys.newLine}stderr: ${stderr}`); - } - // treat any output on stdout as success - onRequestCompleted(!!stdout); - }); - } - break; - default: - Debug.assert(false, `Unknown request kind ${requestKind}`); + this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(args)}'.`); } + const command = `${this.npmPath} install ${args.join(" ")} --save-dev`; + const start = Date.now(); + this.exec(command, { cwd }, (_err, stdout, stderr) => { + if (this.log.isEnabled()) { + this.log.writeLine(`npm install #${requestId} took: ${Date.now() - start} ms${sys.newLine}stdout: ${stdout}${sys.newLine}stderr: ${stderr}`); + } + // treat any output on stdout as success + onRequestCompleted(!!stdout); + }); } } - function findArgument(argumentName: string) { - const index = sys.args.indexOf(argumentName); - return index >= 0 && index < sys.args.length - 1 - ? sys.args[index + 1] - : undefined; - } + const logFilePath = findArgument(server.Arguments.LogFile); + const globalTypingsCacheLocation = findArgument(server.Arguments.GlobalCacheLocation); + const telemetryEnabled = hasArgument(server.Arguments.EnableTelemetry); - const logFilePath = findArgument("--logFile"); - const globalTypingsCacheLocation = findArgument("--globalTypingsCacheLocation"); const log = new FileLog(logFilePath); if (log.isEnabled()) { process.on("uncaughtException", (e: Error) => { @@ -162,6 +161,6 @@ namespace ts.server.typingsInstaller { } process.exit(0); }); - const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, /*throttleLimit*/5, log); - installer.init(); + const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, /*throttleLimit*/5, telemetryEnabled, log); + installer.listen(); } \ No newline at end of file diff --git a/src/server/typingsInstaller/tsconfig.json b/src/server/typingsInstaller/tsconfig.json index c9b4d8f0ad1..c6031b19aae 100644 --- a/src/server/typingsInstaller/tsconfig.json +++ b/src/server/typingsInstaller/tsconfig.json @@ -17,6 +17,7 @@ }, "files": [ "../types.d.ts", + "../shared.ts", "typingsInstaller.ts", "nodeTypingsInstaller.ts" ] diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index df043fc26ae..a602a9f1a26 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -2,6 +2,7 @@ /// /// /// +/// namespace ts.server.typingsInstaller { interface NpmConfig { @@ -63,14 +64,8 @@ namespace ts.server.typingsInstaller { return PackageNameValidationResult.Ok; } - export const NpmViewRequest: "npm view" = "npm view"; - export const NpmInstallRequest: "npm install" = "npm install"; - - export type RequestKind = typeof NpmViewRequest | typeof NpmInstallRequest; - export type RequestCompletedAction = (success: boolean) => void; type PendingRequest = { - requestKind: RequestKind; requestId: number; args: string[]; cwd: string; @@ -87,19 +82,18 @@ namespace ts.server.typingsInstaller { private installRunCount = 1; private inFlightRequestCount = 0; - abstract readonly installTypingHost: InstallTypingHost; + abstract readonly typesRegistry: Map; constructor( + readonly installTypingHost: InstallTypingHost, readonly globalCachePath: string, readonly safeListPath: Path, readonly throttleLimit: number, + readonly telemetryEnabled: boolean, protected readonly log = nullLog) { if (this.log.isEnabled()) { this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}'`); } - } - - init() { this.processCacheLocation(this.globalCachePath); } @@ -224,7 +218,7 @@ namespace ts.server.typingsInstaller { this.knownCachesSet[cacheLocation] = true; } - private filterTypings(typingsToInstall: string[]) { + private filterAndMapToScopedName(typingsToInstall: string[]) { if (typingsToInstall.length === 0) { return typingsToInstall; } @@ -235,7 +229,14 @@ namespace ts.server.typingsInstaller { } const validationResult = validatePackageName(typing); if (validationResult === PackageNameValidationResult.Ok) { - result.push(typing); + if (typing in this.typesRegistry) { + result.push(`@types/${typing}`); + } + else { + if (this.log.isEnabled()) { + this.log.writeLine(`Entry for package '${typing}' does not exist in local types registry - skipping...`); + } + } } else { // add typing name to missing set so we won't process it again @@ -267,19 +268,8 @@ namespace ts.server.typingsInstaller { return result; } - private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) { - if (this.log.isEnabled()) { - this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); - } - typingsToInstall = this.filterTypings(typingsToInstall); - if (typingsToInstall.length === 0) { - if (this.log.isEnabled()) { - this.log.writeLine(`All typings are known to be missing or invalid - no need to go any further`); - } - return; - } - - const npmConfigPath = combinePaths(cachePath, "package.json"); + protected ensurePackageDirectoryExists(directory: string) { + const npmConfigPath = combinePaths(directory, "package.json"); if (this.log.isEnabled()) { this.log.writeLine(`Npm config file: ${npmConfigPath}`); } @@ -287,23 +277,50 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Npm config file: '${npmConfigPath}' is missing, creating new one...`); } - this.ensureDirectoryExists(cachePath, this.installTypingHost); + this.ensureDirectoryExists(directory, this.installTypingHost); this.installTypingHost.writeFile(npmConfigPath, "{}"); } + } + + private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) { + if (this.log.isEnabled()) { + this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); + } + const scopedTypings = this.filterAndMapToScopedName(typingsToInstall); + if (scopedTypings.length === 0) { + if (this.log.isEnabled()) { + this.log.writeLine(`All typings are known to be missing or invalid - no need to go any further`); + } + return; + } + + this.ensurePackageDirectoryExists(cachePath); + + const requestId = this.installRunCount; + this.installRunCount++; + + this.installTypingsAsync(requestId, scopedTypings, cachePath, ok => { + if (this.telemetryEnabled) { + this.sendResponse({ + kind: EventInstall, + packagesToInstall: scopedTypings + }); + } + + if (!ok) { + return; + } - this.runInstall(cachePath, typingsToInstall, installedTypings => { // TODO: watch project directory if (this.log.isEnabled()) { - this.log.writeLine(`Requested to install typings ${JSON.stringify(typingsToInstall)}, installed typings ${JSON.stringify(installedTypings)}`); + this.log.writeLine(`Requested to install typings ${JSON.stringify(scopedTypings)}, installed typings ${JSON.stringify(scopedTypings)}`); } - const installedPackages: Map = createMap(); const installedTypingFiles: string[] = []; - for (const t of installedTypings) { + for (const t of scopedTypings) { const packageName = getBaseFileName(t); if (!packageName) { continue; } - installedPackages[packageName] = true; const typingFile = typingToFileName(cachePath, packageName, this.installTypingHost); if (!typingFile) { continue; @@ -316,53 +333,11 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Installed typing files ${JSON.stringify(installedTypingFiles)}`); } - for (const toInstall of typingsToInstall) { - if (!installedPackages[toInstall]) { - if (this.log.isEnabled()) { - this.log.writeLine(`New missing typing package '${toInstall}'`); - } - this.missingTypingsSet[toInstall] = true; - } - } this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); }); } - private runInstall(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void { - const requestId = this.installRunCount; - - this.installRunCount++; - let execInstallCmdCount = 0; - const filteredTypings: string[] = []; - for (const typing of typingsToInstall) { - filterExistingTypings(this, typing); - } - - function filterExistingTypings(self: TypingsInstaller, typing: string) { - self.execAsync(NpmViewRequest, requestId, [typing], cachePath, ok => { - if (ok) { - filteredTypings.push(typing); - } - execInstallCmdCount++; - if (execInstallCmdCount === typingsToInstall.length) { - installFilteredTypings(self, filteredTypings); - } - }); - } - - function installFilteredTypings(self: TypingsInstaller, filteredTypings: string[]) { - if (filteredTypings.length === 0) { - postInstallAction([]); - return; - } - const scopedTypings = filteredTypings.map(t => "@types/" + t); - self.execAsync(NpmInstallRequest, requestId, scopedTypings, cachePath, ok => { - postInstallAction(ok ? scopedTypings : []); - }); - } - } - private ensureDirectoryExists(directory: string, host: InstallTypingHost): void { const directoryName = getDirectoryPath(directory); if (!host.directoryExists(directoryName)) { @@ -389,7 +364,7 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Got FS notification for ${f}, handler is already invoked '${isInvoked}'`); } if (!isInvoked) { - this.sendResponse({ projectName: projectName, kind: "invalidate" }); + this.sendResponse({ projectName: projectName, kind: server.ActionInvalidate }); isInvoked = true; } }); @@ -405,12 +380,12 @@ namespace ts.server.typingsInstaller { compilerOptions: request.compilerOptions, typings, unresolvedImports: request.unresolvedImports, - kind: "set" + kind: server.ActionSet }; } - private execAsync(requestKind: RequestKind, requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { - this.pendingRunRequests.unshift({ requestKind, requestId, args, cwd, onRequestCompleted }); + private installTypingsAsync(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { + this.pendingRunRequests.unshift({ requestId, args, cwd, onRequestCompleted }); this.executeWithThrottling(); } @@ -418,7 +393,7 @@ namespace ts.server.typingsInstaller { while (this.inFlightRequestCount < this.throttleLimit && this.pendingRunRequests.length) { this.inFlightRequestCount++; const request = this.pendingRunRequests.pop(); - this.executeRequest(request.requestKind, request.requestId, request.args, request.cwd, ok => { + this.installWorker(request.requestId, request.args, request.cwd, ok => { this.inFlightRequestCount--; request.onRequestCompleted(ok); this.executeWithThrottling(); @@ -426,7 +401,7 @@ namespace ts.server.typingsInstaller { } } - protected abstract executeRequest(requestKind: RequestKind, requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; - protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings): void; + protected abstract installWorker(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; + protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | TypingsInstallEvent): void; } } \ No newline at end of file diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 8806b759e3f..9a832d22c8d 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -1,4 +1,5 @@ /// +/// namespace ts.server { export enum LogLevel { @@ -10,6 +11,7 @@ namespace ts.server { export const emptyArray: ReadonlyArray = []; + export interface Logger { close(): void; hasLevel(level: LogLevel): boolean; From 0173a3fa790ca49b74d609c410c77d363e18229d Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 7 Nov 2016 15:48:46 -0800 Subject: [PATCH 19/27] return empty file watcher in case if target directory does not exist (#12091) * return empty file watcher in case if target directory does not exist * linter --- src/compiler/sys.ts | 3 ++- .../unittests/tsserverProjectSystem.ts | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 13bbfc2ab15..9cf95d6de9b 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -439,6 +439,7 @@ namespace ts { return filter(_fs.readdirSync(path), dir => fileSystemEntryExists(combinePaths(path, dir), FileSystemEntryKind.Directory)); } + const noOpFileWatcher: FileWatcher = { close: noop }; const nodeSystem: System = { args: process.argv.slice(2), newLine: _os.EOL, @@ -475,7 +476,7 @@ namespace ts { // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) let options: any; if (!directoryExists(directoryName)) { - return; + return noOpFileWatcher; } if (isNode4OrLater() && (process.platform === "win32" || process.platform === "darwin")) { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index ee6139b1215..c3974f03772 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1964,6 +1964,33 @@ namespace ts.projectSystem { projectService.checkNumberOfProjects({ configuredProjects: 1 }); checkProjectActualFiles(projectService.configuredProjects[0], [libES5.path, libES2015Promise.path, app.path]); }); + + it("should handle non-existing directories in config file", () => { + const f = { + path: "/a/src/app.ts", + content: "let x = 1;" + }; + const config = { + path: "/a/tsconfig.json", + content: JSON.stringify({ + compilerOptions: {}, + include: [ + "src/**/*", + "notexistingfolder/*" + ] + }) + }; + const host = createServerHost([f, config]); + const projectService = createProjectService(host); + projectService.openClientFile(f.path); + projectService.checkNumberOfProjects({ configuredProjects: 1 }); + + projectService.closeClientFile(f.path); + projectService.checkNumberOfProjects({ configuredProjects: 0 }); + + projectService.openClientFile(f.path); + projectService.checkNumberOfProjects({ configuredProjects: 1 }); + }); }); describe("prefer typings to js", () => { From be2e8e85d63f472a5a7762e1e56316026156317c Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 7 Nov 2016 15:49:19 -0800 Subject: [PATCH 20/27] property handle missing config files in external projects (#12094) --- .../unittests/tsserverProjectSystem.ts | 21 +++++++++++++++++++ src/server/editorServices.ts | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index c3974f03772..62c0957d6a3 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2249,6 +2249,27 @@ namespace ts.projectSystem { assert.equal(diags.length, 0); }); + it("should property handle missing config files", () => { + const f1 = { + path: "/a/b/app.ts", + content: "let x = 1" + }; + const config = { + path: "/a/b/tsconfig.json", + content: "{}" + }; + const projectName = "project1"; + const host = createServerHost([f1]); + const projectService = createProjectService(host); + projectService.openExternalProject({ rootFiles: toExternalFiles([f1.path, config.path]), options: {}, projectFileName: projectName }); + + // should have one external project since config file is missing + projectService.checkNumberOfProjects({ externalProjects: 1 }); + + host.reloadFS([f1, config]); + projectService.openExternalProject({ rootFiles: toExternalFiles([f1.path, config.path]), options: {}, projectFileName: projectName }); + projectService.checkNumberOfProjects({ configuredProjects: 1 }); + }); }); describe("add the missing module file for inferred project", () => { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index bf760106b74..269eea06464 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1288,7 +1288,9 @@ namespace ts.server { for (const file of proj.rootFiles) { const normalized = toNormalizedPath(file.fileName); if (getBaseFileName(normalized) === "tsconfig.json") { - (tsConfigFiles || (tsConfigFiles = [])).push(normalized); + if (this.host.fileExists(normalized)) { + (tsConfigFiles || (tsConfigFiles = [])).push(normalized); + } } else { rootFiles.push(file); From ddc4ae7eac9526b5dbd6624f89a2f0308b32b425 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 7 Nov 2016 16:03:04 -0800 Subject: [PATCH 21/27] Reuse subtree transform flags for incrementally parsed nodes (#12088) --- src/compiler/binder.ts | 66 +++++++++++++++++++++- src/compiler/visitor.ts | 60 -------------------- src/harness/unittests/incrementalParser.ts | 24 +++++--- src/services/services.ts | 2 - 4 files changed, 81 insertions(+), 71 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 1d721e2db90..112a53e88ec 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -560,6 +560,7 @@ namespace ts { skipTransformFlagAggregation = true; bindChildrenWorker(node); skipTransformFlagAggregation = false; + subtreeTransformFlags |= node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); } else { const savedSubtreeTransformFlags = subtreeTransformFlags; @@ -895,8 +896,8 @@ namespace ts { const enclosingLabeledStatement = node.parent.kind === SyntaxKind.LabeledStatement ? lastOrUndefined(activeLabels) : undefined; - // if do statement is wrapped in labeled statement then target labels for break/continue with or without - // label should be the same + // if do statement is wrapped in labeled statement then target labels for break/continue with or without + // label should be the same const preConditionLabel = enclosingLabeledStatement ? enclosingLabeledStatement.continueTarget : createBranchLabel(); const postDoLabel = enclosingLabeledStatement ? enclosingLabeledStatement.breakTarget : createBranchLabel(); addAntecedent(preDoLabel, currentFlow); @@ -3206,4 +3207,65 @@ namespace ts { node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; return transformFlags & ~excludeFlags; } + + /** + * Gets the transform flags to exclude when unioning the transform flags of a subtree. + * + * NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`. + * For performance reasons, `computeTransformFlagsForNode` uses local constant values rather + * than calling this function. + */ + /* @internal */ + export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) { + if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) { + return TransformFlags.TypeExcludes; + } + + switch (kind) { + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.ArrayLiteralExpression: + return TransformFlags.ArrayLiteralOrCallOrNewExcludes; + case SyntaxKind.ModuleDeclaration: + return TransformFlags.ModuleExcludes; + case SyntaxKind.Parameter: + return TransformFlags.ParameterExcludes; + case SyntaxKind.ArrowFunction: + return TransformFlags.ArrowFunctionExcludes; + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + return TransformFlags.FunctionExcludes; + case SyntaxKind.VariableDeclarationList: + return TransformFlags.VariableDeclarationListExcludes; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + return TransformFlags.ClassExcludes; + case SyntaxKind.Constructor: + return TransformFlags.ConstructorExcludes; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return TransformFlags.MethodOrAccessorExcludes; + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.TypeParameter: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + return TransformFlags.TypeExcludes; + case SyntaxKind.ObjectLiteralExpression: + return TransformFlags.ObjectLiteralExcludes; + default: + return TransformFlags.NodeExcludes; + } + } } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 45b82a6a08a..34cc2e07436 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -1270,66 +1270,6 @@ namespace ts { return transformFlags | aggregateTransformFlagsForNode(child); } - /** - * Gets the transform flags to exclude when unioning the transform flags of a subtree. - * - * NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`. - * For performance reasons, `computeTransformFlagsForNode` uses local constant values rather - * than calling this function. - */ - function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) { - if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) { - return TransformFlags.TypeExcludes; - } - - switch (kind) { - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.ArrayLiteralExpression: - return TransformFlags.ArrayLiteralOrCallOrNewExcludes; - case SyntaxKind.ModuleDeclaration: - return TransformFlags.ModuleExcludes; - case SyntaxKind.Parameter: - return TransformFlags.ParameterExcludes; - case SyntaxKind.ArrowFunction: - return TransformFlags.ArrowFunctionExcludes; - case SyntaxKind.FunctionExpression: - case SyntaxKind.FunctionDeclaration: - return TransformFlags.FunctionExcludes; - case SyntaxKind.VariableDeclarationList: - return TransformFlags.VariableDeclarationListExcludes; - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - return TransformFlags.ClassExcludes; - case SyntaxKind.Constructor: - return TransformFlags.ConstructorExcludes; - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return TransformFlags.MethodOrAccessorExcludes; - case SyntaxKind.AnyKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.NeverKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.VoidKeyword: - case SyntaxKind.TypeParameter: - case SyntaxKind.PropertySignature: - case SyntaxKind.MethodSignature: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - return TransformFlags.TypeExcludes; - case SyntaxKind.ObjectLiteralExpression: - return TransformFlags.ObjectLiteralExcludes; - default: - return TransformFlags.NodeExcludes; - } - } - export namespace Debug { export const failNotOptional = shouldAssert(AssertionLevel.Normal) ? (message?: string) => assert(false, message || "Node not optional.") diff --git a/src/harness/unittests/incrementalParser.ts b/src/harness/unittests/incrementalParser.ts index 0082207e699..6088e5fe082 100644 --- a/src/harness/unittests/incrementalParser.ts +++ b/src/harness/unittests/incrementalParser.ts @@ -44,10 +44,10 @@ namespace ts { // NOTE: 'reusedElements' is the expected count of elements reused from the old tree to the new // tree. It may change as we tweak the parser. If the count increases then that should always - // be a good thing. If it decreases, that's not great (less reusability), but that may be - // unavoidable. If it does decrease an investigation should be done to make sure that things + // be a good thing. If it decreases, that's not great (less reusability), but that may be + // unavoidable. If it does decrease an investigation should be done to make sure that things // are still ok and we're still appropriately reusing most of the tree. - function compareTrees(oldText: IScriptSnapshot, newText: IScriptSnapshot, textChangeRange: TextChangeRange, expectedReusedElements: number, oldTree?: SourceFile): SourceFile { + function compareTrees(oldText: IScriptSnapshot, newText: IScriptSnapshot, textChangeRange: TextChangeRange, expectedReusedElements: number, oldTree?: SourceFile) { oldTree = oldTree || createTree(oldText, /*version:*/ "."); Utils.assertInvariants(oldTree, /*parent:*/ undefined); @@ -76,7 +76,7 @@ namespace ts { assert.equal(actualReusedCount, expectedReusedElements, actualReusedCount + " !== " + expectedReusedElements); } - return incrementalNewTree; + return { oldTree, newTree, incrementalNewTree }; } function reusedElements(oldNode: SourceFile, newNode: SourceFile): number { @@ -103,7 +103,7 @@ namespace ts { for (let i = 0; i < repeat; i++) { const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index, 1); - const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree); + const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree).incrementalNewTree; source = newTextAndChange.text.getText(0, newTextAndChange.text.getLength()); oldTree = newTree; @@ -116,7 +116,7 @@ namespace ts { for (let i = 0; i < repeat; i++) { const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + i, toInsert.charAt(i)); - const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree); + const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree).incrementalNewTree; source = newTextAndChange.text.getText(0, newTextAndChange.text.getLength()); oldTree = newTree; @@ -639,7 +639,7 @@ module m3 { }\ }); it("Unterminated comment after keyword converted to identifier", () => { - // 'public' as a keyword should be incrementally unusable (because it has an + // 'public' as a keyword should be incrementally unusable (because it has an // unterminated comment). When we convert it to an identifier, that shouldn't // change anything, and we should still get the same errors. const source = "return; a.public /*"; @@ -796,6 +796,16 @@ module m3 { }\ compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); }); + it("Reuse transformFlags of subtree during bind", () => { + const source = `class Greeter { constructor(element: HTMLElement) { } }`; + const oldText = ScriptSnapshot.fromString(source); + const newTextAndChange = withChange(oldText, 15, 0, "\n"); + const { oldTree, incrementalNewTree } = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); + bindSourceFile(oldTree, {}); + bindSourceFile(incrementalNewTree, {}); + assert.equal(oldTree.transformFlags, incrementalNewTree.transformFlags); + }); + // Simulated typing tests. it("Type extends clause 1", () => { diff --git a/src/services/services.ts b/src/services/services.ts index 8abcf8f7684..56e604abeb3 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -48,7 +48,6 @@ namespace ts { public jsDocComments: JSDoc[]; public original: Node; public transformFlags: TransformFlags; - public excludeTransformFlags: TransformFlags; private _children: Node[]; constructor(kind: SyntaxKind, pos: number, end: number) { @@ -56,7 +55,6 @@ namespace ts { this.end = end; this.flags = NodeFlags.None; this.transformFlags = undefined; - this.excludeTransformFlags = undefined; this.parent = undefined; this.kind = kind; } From 2bf38ab6cd6a2321b2422a503573d492115d3457 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 7 Nov 2016 21:09:17 -0800 Subject: [PATCH 22/27] Port fix for https://github.com/Microsoft/TypeScript/issues/12069 (#12095) --- src/lib/dom.generated.d.ts | 4 ++-- src/lib/webworker.generated.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 9a87020d4f0..fd77f369fd8 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -7586,7 +7586,7 @@ declare var IDBCursorWithValue: { interface IDBDatabase extends EventTarget { readonly name: string; - readonly objectStoreNames: string[]; + readonly objectStoreNames: DOMStringList; onabort: (this: this, ev: Event) => any; onerror: (this: this, ev: ErrorEvent) => any; version: number; @@ -7652,7 +7652,7 @@ declare var IDBKeyRange: { } interface IDBObjectStore { - readonly indexNames: string[]; + readonly indexNames: DOMStringList; keyPath: string | string[]; readonly name: string; readonly transaction: IDBTransaction; diff --git a/src/lib/webworker.generated.d.ts b/src/lib/webworker.generated.d.ts index 4aeba696306..130510334d6 100644 --- a/src/lib/webworker.generated.d.ts +++ b/src/lib/webworker.generated.d.ts @@ -341,7 +341,7 @@ declare var IDBCursorWithValue: { interface IDBDatabase extends EventTarget { readonly name: string; - readonly objectStoreNames: string[]; + readonly objectStoreNames: DOMStringList; onabort: (this: this, ev: Event) => any; onerror: (this: this, ev: ErrorEvent) => any; version: number; @@ -407,7 +407,7 @@ declare var IDBKeyRange: { } interface IDBObjectStore { - readonly indexNames: string[]; + readonly indexNames: DOMStringList; keyPath: string | string[]; readonly name: string; readonly transaction: IDBTransaction; From 9e3d6efb199520ac66529b933e549e432cd1776c Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 7 Nov 2016 21:13:11 -0800 Subject: [PATCH 23/27] reduce set of files being watched, increase polling interval (#12054) (#12092) --- src/compiler/program.ts | 7 ++++++- src/compiler/sys.ts | 10 +++++++--- src/compiler/types.ts | 1 + src/server/project.ts | 12 +++++++++--- src/server/types.d.ts | 2 +- src/server/typingsInstaller/typingsInstaller.ts | 2 +- src/server/utilities.ts | 2 +- src/services/jsTyping.ts | 2 +- 8 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index dcb9cce0adb..1b36d99d7c9 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -420,6 +420,7 @@ namespace ts { getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(), getFileProcessingDiagnostics: () => fileProcessingDiagnostics, getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives, + isSourceFileFromExternalLibrary, dropDiagnosticsProducingTypeChecker }; @@ -722,13 +723,17 @@ namespace ts { getSourceFile: program.getSourceFile, getSourceFileByPath: program.getSourceFileByPath, getSourceFiles: program.getSourceFiles, - isSourceFileFromExternalLibrary: (file: SourceFile) => !!sourceFilesFoundSearchingNodeModules[file.path], + isSourceFileFromExternalLibrary, writeFile: writeFileCallback || ( (fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)), isEmitBlocked, }; } + function isSourceFileFromExternalLibrary(file: SourceFile): boolean { + return sourceFilesFoundSearchingNodeModules[file.path]; + } + function getDiagnosticsProducingTypeChecker() { return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true)); } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 9cf95d6de9b..a1e82a66595 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -17,7 +17,11 @@ namespace ts { readFile(path: string, encoding?: string): string; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; - watchFile?(path: string, callback: FileWatcherCallback): FileWatcher; + /** + * @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that + * use native OS file watching + */ + watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; @@ -449,7 +453,7 @@ namespace ts { }, readFile, writeFile, - watchFile: (fileName, callback) => { + watchFile: (fileName, callback, pollingInterval) => { if (useNonPollingWatchers) { const watchedFile = watchedFileSet.addFile(fileName, callback); return { @@ -457,7 +461,7 @@ namespace ts { }; } else { - _fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged); + _fs.watchFile(fileName, { persistent: true, interval: pollingInterval || 250 }, fileChanged); return { close: () => _fs.unwatchFile(fileName, fileChanged) }; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 37a3cc466a0..aa0b3e505f6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2192,6 +2192,7 @@ namespace ts { /* @internal */ getFileProcessingDiagnostics(): DiagnosticCollection; /* @internal */ getResolvedTypeReferenceDirectives(): Map; + /* @internal */ isSourceFileFromExternalLibrary(file: SourceFile): boolean; // For testing purposes only. /* @internal */ structureIsReused?: boolean; } diff --git a/src/server/project.ts b/src/server/project.ts index 563b0456910..d01df728248 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -301,7 +301,7 @@ namespace ts.server { return this.getLanguageService().getEmitOutput(info.fileName, emitOnlyDtsFiles); } - getFileNames() { + getFileNames(excludeFilesFromExternalLibraries?: boolean) { if (!this.program) { return []; } @@ -317,8 +317,14 @@ namespace ts.server { } return rootFiles; } - const sourceFiles = this.program.getSourceFiles(); - return sourceFiles.map(sourceFile => asNormalizedPath(sourceFile.fileName)); + const result: NormalizedPath[] = []; + for (const f of this.program.getSourceFiles()) { + if (excludeFilesFromExternalLibraries && this.program.isSourceFileFromExternalLibrary(f)) { + continue; + } + result.push(asNormalizedPath(f.fileName)); + } + return result; } getAllEmittableFiles() { diff --git a/src/server/types.d.ts b/src/server/types.d.ts index 95f9519cc38..aebc3121252 100644 --- a/src/server/types.d.ts +++ b/src/server/types.d.ts @@ -73,6 +73,6 @@ declare namespace ts.server { export interface InstallTypingHost extends JsTyping.TypingResolutionHost { writeFile(path: string, content: string): void; createDirectory(path: string): void; - watchFile?(path: string, callback: FileWatcherCallback): FileWatcher; + watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; } } \ No newline at end of file diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index a602a9f1a26..da97dbcd194 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -367,7 +367,7 @@ namespace ts.server.typingsInstaller { this.sendResponse({ projectName: projectName, kind: server.ActionInvalidate }); isInvoked = true; } - }); + }, /*pollingInterval*/ 2000); watchers.push(w); } this.projectWatchers[projectName] = watchers; diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 9a832d22c8d..ac809652119 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -50,7 +50,7 @@ namespace ts.server { export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray, cachePath?: string): DiscoverTypings { return { projectName: project.getProjectName(), - fileNames: project.getFileNames(), + fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true), compilerOptions: project.getCompilerOptions(), typingOptions, unresolvedImports, diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 0f635c15174..316dcd355c2 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -88,7 +88,7 @@ namespace ts.JsTyping { exclude = typingOptions.exclude || []; const possibleSearchDirs = map(fileNames, getDirectoryPath); - if (projectRootPath !== undefined) { + if (projectRootPath) { possibleSearchDirs.push(projectRootPath); } searchDirs = deduplicate(possibleSearchDirs); From 84f8f8bba89ff459180852179c31ea7e9105736d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 7 Nov 2016 21:58:53 -0800 Subject: [PATCH 24/27] Update authors for release-2.1 --- .mailmap | 43 ++++++++++++++++++++++++++++++++++++------- AUTHORS.md | 32 +++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/.mailmap b/.mailmap index e66f669b8ee..cc101c0517e 100644 --- a/.mailmap +++ b/.mailmap @@ -1,32 +1,38 @@  -Alexander # Alexander Kuvaev AbubakerB # Abubaker Bashir +Alexander # Alexander Kuvaev Adam Freidin Adam Freidin Adi Dahiya Adi Dahiya Ahmad Farid ahmad-farid +Alexander Rusakov Alex Eagle +Anatoly Ressin Anders Hejlsberg unknown unknown +Andrej Baran Andrew Z Allen Andy Hanson Andy Anil Anar Anton Tolmachev Arnavion # Arnav Singh -Arthur Ozga Arthur Ozga +Arthur Ozga Arthur Ozga Arthur Ozga Arthur Ozga Arthur Ozga Asad Saeeduddin Schmavery # Avery Morin Basarat Ali Syed Basarat Syed basarat Bill Ticehurst Bill Ticehurst Ben Duffield +Ben Mosher Blake Embrey Bowden Kelly Brett Mayen Bryan Forbes Caitlin Potter ChrisBubernak unknown # Chris Bubernak +Christophe Vidal Chuck Jazdzewski Colby Russell Colin Snover Cyrus Najmabadi CyrusNajmabadi unknown +Dafrok # Dafrok Zhang Dan Corder Dan Quirk Dan Quirk nknown Daniel Rosenwasser Daniel Rosenwasser Daniel Rosenwasser Daniel Rosenwasser Daniel Rosenwasser @@ -36,17 +42,22 @@ Denis Nedelyaev Dick van den Brink unknown unknown Dirk Baeumer Dirk Bäumer # Dirk Bäumer Dirk Holtwick +Dom Chen Doug Ilijev Erik Edrosa +erictsangx # Eric Tsang Ethan Rubio Evan Martin Evan Sebastian Eyas # Eyas Sharaiha +Fabian Cook falsandtru # @falsandtru Frank Wallis -František Žiačik František Žiačik +František Žiacik František Žiacik +Gabe Moothart Gabriel Isenberg Gilad Peleg +Godfrey Chan Graeme Wicksted Guillaume Salles Guy Bedford guybedford @@ -55,6 +66,7 @@ Iain Monro Ingvar Stepanyan impinball # Isiah Meadows Ivo Gabe de Wolff +Jakub Młokosiewicz James Whitney Jason Freeman Jason Freeman Jason Killian @@ -69,11 +81,14 @@ Jonathan Park Jonathan Turner Jonathan Turner Jonathan Toland Jesse Schalken +Josh Abernathy joshaber Josh Kalderimis Josh Soref Juan Luis Boya García Julian Williams -Herrington Darkholme +Justin Bay +Justin Johansson +Herrington Darkholme (´·?·`) # Herrington Darkholme Kagami Sascha Rosylight SaschaNaz Kanchalai Tanglertsampan Yui Kanchalai Tanglertsampan Yui T @@ -82,23 +97,29 @@ Kanchalai Tanglertsampan Yui Kanchalai Tanglertsampan yui T Keith Mashinter kmashint Ken Howard +Kevin Lang kimamula # Kenji Imamula Kyle Kelley Lorant Pinter Lucien Greathouse +Lukas Elmer Lukas Elmer Martin Vseticka Martin Všeticka MartyIX +gcnew # Marin Marinov vvakame # Masahiro Wakame Matt McCutchen Max Deepfield Micah Zoltu +Michael Mohamed Hegazy Nathan Shively-Sanders Nathan Yee Nima Zahedi +Noah Chen Noj Vek mihailik # Oleg Mihailik Oleksandr Chekhovskyi Paul van Brenk Paul van Brenk unknown unknown unknown +Omer Sheikh Oskar Segersva¨rd pcan # Piero Cangianiello pcbro <2bux89+dk3zspjmuh16o@sharklasers.com> # @pcbro @@ -109,21 +130,26 @@ progre # @progre Prayag Verma Punya Biswal Rado Kirov -Ron Buckton Ron Buckton +Ron Buckton Ron Buckton rbuckton +Rostislav Galimsky Richard Knoll Richard Knoll Rowan Wyborn Ryan Cavanaugh Ryan Cavanaugh Ryan Cavanaugh Ryohei Ikegami Sarangan Rajamanickam Sébastien Arod +Sergey Shandar Sheetal Nandi Shengping Zhong shyyko.serhiy@gmail.com # Shyyko Serhiy +Sam El-Husseini Simon Hürlimann +Slawomir Sadziak Solal Pirelli Stan Thomas Stanislav Sysoev Steve Lucco steveluc +Sudheesh Singanamalla Tarik # Tarik Ozket Tetsuharu OHZEKI # Tetsuharu Ohzeki Tien Nguyen tien unknown #Tien Hoanhtien @@ -133,6 +159,7 @@ Tingan Ho togru # togru Tomas Grubliauskas ToddThomson # Todd Thomson +Torben Fitschen TruongSinh Tran-Nguyen vilicvane # Vilic Vane Vladimir Matveev vladima v2m @@ -140,7 +167,9 @@ Wesley Wigham Wesley Wigham York Yao york yao yaoyao Yuichi Nukiyama YuichiNukiyama Zev Spitz -Zhengbo Li zhengbli Zhengbo Li Zhengbo Li tinza123 unknown Zhengbo Li +Zhengbo Li zhengbli Zhengbo Li Zhengbo Li tinza123 unknown Zhengbo Li zhengbli zhongsp # Patrick Zhong T18970237136 # @T18970237136 -JBerger \ No newline at end of file +JBerger +bootstraponline # @bootstraponline +yortus # @yortus \ No newline at end of file diff --git a/AUTHORS.md b/AUTHORS.md index 08039127d9d..50f1ea12c2b 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -5,7 +5,10 @@ TypeScript is authored by: * Ahmad Farid * Alex Eagle * Alexander Kuvaev +* Alexander Rusakov +* Anatoly Ressin * Anders Hejlsberg +* Andrej Baran * Andrew Z Allen * Andy Hanson * Anil Anar @@ -16,17 +19,21 @@ TypeScript is authored by: * Avery Morin * Basarat Ali Syed * Ben Duffield +* Ben Mosher * Bill Ticehurst * Blake Embrey +* @bootstraponline * Bowden Kelly * Brett Mayen * Bryan Forbes * Caitlin Potter * Chris Bubernak +* Christophe Vidal * Chuck Jazdzewski * Colby Russell * Colin Snover * Cyrus Najmabadi +* Dafrok Zhang * Dan Corder * Dan Quirk * Daniel Rosenwasser @@ -36,17 +43,22 @@ TypeScript is authored by: * Dick van den Brink * Dirk Bäumer * Dirk Holtwick +* Dom Chen * Doug Ilijev +* Eric Tsang * Erik Edrosa * Ethan Rubio * Evan Martin * Evan Sebastian * Eyas Sharaiha +* Fabian Cook * @falsandtru * Frank Wallis -* František Žiačik +* František Žiacik +* Gabe Moothart * Gabriel Isenberg * Gilad Peleg +* Godfrey Chan * Graeme Wicksted * Guillaume Salles * Guy Bedford @@ -56,6 +68,7 @@ TypeScript is authored by: * Ingvar Stepanyan * Isiah Meadows * Ivo Gabe de Wolff +* Jakub Młokosiewicz * James Whitney * Jason Freeman * Jason Killian @@ -71,30 +84,39 @@ TypeScript is authored by: * Jonathan Park * Jonathan Toland * Jonathan Turner +* Josh Abernathy * Josh Kalderimis * Josh Soref * Juan Luis Boya García * Julian Williams +* Justin Bay +* Justin Johansson * Kagami Sascha Rosylight * Kanchalai Tanglertsampan * Keith Mashinter * Ken Howard * Kenji Imamula +* Kevin Lang * Kyle Kelley * Lorant Pinter * Lucien Greathouse +* Lukas Elmer +* Marin Marinov * Martin Vseticka * Masahiro Wakame * Matt McCutchen * Max Deepfield * Micah Zoltu +* Michael * Mohamed Hegazy * Nathan Shively-Sanders * Nathan Yee * Nima Zahedi +* Noah Chen * Noj Vek * Oleg Mihailik * Oleksandr Chekhovskyi +* Omer Sheikh * Oskar Segersva¨rd * Patrick Zhong * Paul van Brenk @@ -109,21 +131,27 @@ TypeScript is authored by: * Rado Kirov * Richard Knoll * Ron Buckton +* Rostislav Galimsky * Rowan Wyborn * Ryan Cavanaugh * Ryohei Ikegami +* Sam El-Husseini * Sarangan Rajamanickam +* Sergey Shandar * Sheetal Nandi * Shengping Zhong * Shyyko Serhiy * Simon Hürlimann +* Slawomir Sadziak * Solal Pirelli * Stan Thomas * Stanislav Sysoev * Steve Lucco +* Sudheesh Singanamalla * Sébastien Arod * @T18970237136 * Tarik Ozket +* Tetsuharu Ohzeki * Tien Hoanhtien * Tim Perry * Tim Viiding-Spader @@ -131,11 +159,13 @@ TypeScript is authored by: * Todd Thomson * togru * Tomas Grubliauskas +* Torben Fitschen * TruongSinh Tran-Nguyen * Vilic Vane * Vladimir Matveev * Wesley Wigham * York Yao +* @yortus * Yuichi Nukiyama * Zev Spitz * Zhengbo Li \ No newline at end of file From be0358cc0cff88b0e5b05e656735da80a052c0f6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 8 Nov 2016 06:09:41 -0800 Subject: [PATCH 25/27] Include declaration file emit --- .../reference/instantiatedTypeAliasDisplay.js | 15 ++++ .../instantiatedTypeAliasDisplay.symbols | 75 ++++++++++--------- .../instantiatedTypeAliasDisplay.types | 1 + .../compiler/instantiatedTypeAliasDisplay.ts | 2 + 4 files changed, 56 insertions(+), 37 deletions(-) diff --git a/tests/baselines/reference/instantiatedTypeAliasDisplay.js b/tests/baselines/reference/instantiatedTypeAliasDisplay.js index 86b17262e0f..9c2b91b613e 100644 --- a/tests/baselines/reference/instantiatedTypeAliasDisplay.js +++ b/tests/baselines/reference/instantiatedTypeAliasDisplay.js @@ -1,4 +1,5 @@ //// [instantiatedTypeAliasDisplay.ts] + // Repros from #12066 interface X { @@ -19,3 +20,17 @@ const x2 = f2({}, {}, {}, {}); // Z<{}, string[]> // Repros from #12066 var x1 = f1(); // Z var x2 = f2({}, {}, {}, {}); // Z<{}, string[]> + + +//// [instantiatedTypeAliasDisplay.d.ts] +interface X { + a: A; +} +interface Y { + b: B; +} +declare type Z = X | Y; +declare function f1(): Z; +declare function f2(a: A, b: B, c: C, d: D): Z; +declare const x1: Z; +declare const x2: Z<{}, string[]>; diff --git a/tests/baselines/reference/instantiatedTypeAliasDisplay.symbols b/tests/baselines/reference/instantiatedTypeAliasDisplay.symbols index 3c6f7d2b725..fa8140cfcd7 100644 --- a/tests/baselines/reference/instantiatedTypeAliasDisplay.symbols +++ b/tests/baselines/reference/instantiatedTypeAliasDisplay.symbols @@ -1,60 +1,61 @@ === tests/cases/compiler/instantiatedTypeAliasDisplay.ts === + // Repros from #12066 interface X { >X : Symbol(X, Decl(instantiatedTypeAliasDisplay.ts, 0, 0)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 2, 12)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 3, 12)) a: A; ->a : Symbol(X.a, Decl(instantiatedTypeAliasDisplay.ts, 2, 16)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 2, 12)) +>a : Symbol(X.a, Decl(instantiatedTypeAliasDisplay.ts, 3, 16)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 3, 12)) } interface Y { ->Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 4, 1)) ->B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 5, 12)) +>Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 5, 1)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 6, 12)) b: B; ->b : Symbol(Y.b, Decl(instantiatedTypeAliasDisplay.ts, 5, 16)) ->B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 5, 12)) +>b : Symbol(Y.b, Decl(instantiatedTypeAliasDisplay.ts, 6, 16)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 6, 12)) } type Z = X | Y; ->Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 7, 1)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 8, 7)) ->B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 8, 9)) +>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 9, 7)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 9, 9)) >X : Symbol(X, Decl(instantiatedTypeAliasDisplay.ts, 0, 0)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 8, 7)) ->Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 4, 1)) ->B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 8, 9)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 9, 7)) +>Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 5, 1)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 9, 9)) declare function f1(): Z; ->f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 8, 27)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 10, 20)) ->Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 7, 1)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 10, 20)) +>f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 9, 27)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20)) +>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20)) declare function f2(a: A, b: B, c: C, d: D): Z; ->f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 10, 39)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20)) ->B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 11, 22)) ->C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 11, 25)) ->D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 11, 28)) ->E : Symbol(E, Decl(instantiatedTypeAliasDisplay.ts, 11, 31)) ->a : Symbol(a, Decl(instantiatedTypeAliasDisplay.ts, 11, 35)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20)) ->b : Symbol(b, Decl(instantiatedTypeAliasDisplay.ts, 11, 40)) ->B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 11, 22)) ->c : Symbol(c, Decl(instantiatedTypeAliasDisplay.ts, 11, 46)) ->C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 11, 25)) ->d : Symbol(d, Decl(instantiatedTypeAliasDisplay.ts, 11, 52)) ->D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 11, 28)) ->Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 7, 1)) ->A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20)) +>f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 11, 39)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 12, 22)) +>C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 12, 25)) +>D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 12, 28)) +>E : Symbol(E, Decl(instantiatedTypeAliasDisplay.ts, 12, 31)) +>a : Symbol(a, Decl(instantiatedTypeAliasDisplay.ts, 12, 35)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20)) +>b : Symbol(b, Decl(instantiatedTypeAliasDisplay.ts, 12, 40)) +>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 12, 22)) +>c : Symbol(c, Decl(instantiatedTypeAliasDisplay.ts, 12, 46)) +>C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 12, 25)) +>d : Symbol(d, Decl(instantiatedTypeAliasDisplay.ts, 12, 52)) +>D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 12, 28)) +>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1)) +>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20)) const x1 = f1(); // Z ->x1 : Symbol(x1, Decl(instantiatedTypeAliasDisplay.ts, 13, 5)) ->f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 8, 27)) +>x1 : Symbol(x1, Decl(instantiatedTypeAliasDisplay.ts, 14, 5)) +>f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 9, 27)) const x2 = f2({}, {}, {}, {}); // Z<{}, string[]> ->x2 : Symbol(x2, Decl(instantiatedTypeAliasDisplay.ts, 14, 5)) ->f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 10, 39)) +>x2 : Symbol(x2, Decl(instantiatedTypeAliasDisplay.ts, 15, 5)) +>f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 11, 39)) diff --git a/tests/baselines/reference/instantiatedTypeAliasDisplay.types b/tests/baselines/reference/instantiatedTypeAliasDisplay.types index 44885777e74..89320e1dba6 100644 --- a/tests/baselines/reference/instantiatedTypeAliasDisplay.types +++ b/tests/baselines/reference/instantiatedTypeAliasDisplay.types @@ -1,4 +1,5 @@ === tests/cases/compiler/instantiatedTypeAliasDisplay.ts === + // Repros from #12066 interface X { diff --git a/tests/cases/compiler/instantiatedTypeAliasDisplay.ts b/tests/cases/compiler/instantiatedTypeAliasDisplay.ts index d2abaaf8afe..8f7500e7830 100644 --- a/tests/cases/compiler/instantiatedTypeAliasDisplay.ts +++ b/tests/cases/compiler/instantiatedTypeAliasDisplay.ts @@ -1,3 +1,5 @@ +// @declaration: true + // Repros from #12066 interface X { From 9a9f45f0fbafebb0b52b524db8448d8330c5984b Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 8 Nov 2016 15:32:53 -0800 Subject: [PATCH 26/27] use createHash from ServerHost instead of explicit require (#12043) * use createHash from ServerHost instead of explicit require * added missing method in ServerHost stub --- src/harness/harnessLanguageService.ts | 4 ++++ src/harness/unittests/cachingInServerLSHost.ts | 3 ++- src/harness/unittests/session.ts | 3 ++- src/harness/unittests/tsserverProjectSystem.ts | 4 ++++ src/server/builder.ts | 13 +------------ src/server/editorServices.ts | 2 ++ 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 889d4f28ce9..a49f8926729 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -720,6 +720,10 @@ namespace Harness.LanguageService { clearImmediate(timeoutId: any): void { clearImmediate(timeoutId); } + + createHash(s: string) { + return s; + } } export class ServerLanguageServiceAdapter implements LanguageServiceAdapter { diff --git a/src/harness/unittests/cachingInServerLSHost.ts b/src/harness/unittests/cachingInServerLSHost.ts index 1100bb3663b..4286d3555d8 100644 --- a/src/harness/unittests/cachingInServerLSHost.ts +++ b/src/harness/unittests/cachingInServerLSHost.ts @@ -43,7 +43,8 @@ namespace ts { setTimeout, clearTimeout, setImmediate: typeof setImmediate !== "undefined" ? setImmediate : action => setTimeout(action, 0), - clearImmediate: typeof clearImmediate !== "undefined" ? clearImmediate : clearTimeout + clearImmediate: typeof clearImmediate !== "undefined" ? clearImmediate : clearTimeout, + createHash: s => s }; } diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 05f62c4b9f6..8800e84474b 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -24,7 +24,8 @@ namespace ts.server { setTimeout() { return 0; }, clearTimeout: noop, setImmediate: () => 0, - clearImmediate: noop + clearImmediate: noop, + createHash: s => s }; const nullCancellationToken: HostCancellationToken = { isCancellationRequested: () => false }; const mockLogger: Logger = { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 62c0957d6a3..17b1dd3e585 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -434,6 +434,10 @@ namespace ts.projectSystem { }; } + createHash(s: string): string { + return s; + } + triggerDirectoryWatcherCallback(directoryName: string, fileName: string): void { const path = this.toPath(directoryName); const callbacks = this.watchedDirectories[path]; diff --git a/src/server/builder.ts b/src/server/builder.ts index 548a3ac854c..5354e7ed508 100644 --- a/src/server/builder.ts +++ b/src/server/builder.ts @@ -5,15 +5,6 @@ namespace ts.server { - interface Hash { - update(data: any, input_encoding?: string): Hash; - digest(encoding: string): any; - } - - const crypto: { - createHash(algorithm: string): Hash - } = require("crypto"); - export function shouldEmitFile(scriptInfo: ScriptInfo) { return !scriptInfo.hasMixedContent; } @@ -49,9 +40,7 @@ namespace ts.server { } private computeHash(text: string): string { - return crypto.createHash("md5") - .update(text) - .digest("base64"); + return this.project.projectService.host.createHash(text); } private getSourceFile(): SourceFile { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 269eea06464..d7dcfc810b4 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -250,6 +250,8 @@ namespace ts.server { readonly typingsInstaller: ITypingsInstaller = nullTypingsInstaller, private readonly eventHandler?: ProjectServiceEventHandler) { + Debug.assert(!!host.createHash, "'ServerHost.createHash' is required for ProjectService"); + this.toCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames); this.directoryWatchers = new DirectoryWatchers(this); this.throttledOperations = new ThrottledOperations(host); From 28cc9385035a65f5dcd74a4f9b47e7022678302f Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 8 Nov 2016 16:10:34 -0800 Subject: [PATCH 27/27] (signature help) type parameter lists are never variadic (#12112) --- src/harness/fourslash.ts | 10 +++++++++- src/services/signatureHelp.ts | 5 ++++- tests/cases/fourslash/fourslash.ts | 1 + .../signatureHelpTypeParametersNotVariadic.ts | 8 ++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/signatureHelpTypeParametersNotVariadic.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ae32fe3db16..6ff4dccdee3 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1026,7 +1026,7 @@ namespace FourSlash { ts.displayPartsToString(help.suffixDisplayParts), expected); } - public verifyCurrentParameterIsletiable(isVariable: boolean) { + public verifyCurrentParameterIsVariable(isVariable: boolean) { const signature = this.getActiveSignatureHelpItem(); assert.isOk(signature); assert.equal(isVariable, signature.isVariadic); @@ -1053,6 +1053,10 @@ namespace FourSlash { assert.equal(this.getActiveSignatureHelpItem().parameters.length, expectedCount); } + public verifyCurrentSignatureHelpIsVariadic(expected: boolean) { + assert.equal(this.getActiveSignatureHelpItem().isVariadic, expected); + } + public verifyCurrentSignatureHelpDocComment(docComment: string) { const actualDocComment = this.getActiveSignatureHelpItem().documentation; assert.equal(ts.displayPartsToString(actualDocComment), docComment, this.assertionMessageAtLastKnownMarker("current signature help doc comment")); @@ -3231,6 +3235,10 @@ namespace FourSlashInterface { this.state.verifySignatureHelpCount(expected); } + public signatureHelpCurrentArgumentListIsVariadic(expected: boolean) { + this.state.verifyCurrentSignatureHelpIsVariadic(expected); + } + public signatureHelpArgumentCountIs(expected: number) { this.state.verifySignatureHelpArgumentCount(expected); } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 211e55b23ba..44c2ede9fbb 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -557,7 +557,9 @@ namespace ts.SignatureHelp { addRange(prefixDisplayParts, callTargetDisplayParts); } + let isVariadic: boolean; if (isTypeParameterList) { + isVariadic = false; // type parameter lists are not variadic prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken)); const typeParameters = candidateSignature.typeParameters; signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; @@ -567,6 +569,7 @@ namespace ts.SignatureHelp { addRange(suffixDisplayParts, parameterParts); } else { + isVariadic = candidateSignature.hasRestParameter; const typeParameterParts = mapToDisplayParts(writer => typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation)); addRange(prefixDisplayParts, typeParameterParts); @@ -582,7 +585,7 @@ namespace ts.SignatureHelp { addRange(suffixDisplayParts, returnTypeParts); return { - isVariadic: candidateSignature.hasRestParameter, + isVariadic, prefixDisplayParts, suffixDisplayParts, separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()], diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 0a72d295295..295b8e422b9 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -194,6 +194,7 @@ declare namespace FourSlashInterface { currentSignatureHelpDocCommentIs(docComment: string): void; signatureHelpCountIs(expected: number): void; signatureHelpArgumentCountIs(expected: number): void; + signatureHelpCurrentArgumentListIsVariadic(expected: boolean); currentSignatureParameterCountIs(expected: number): void; currentSignatureTypeParameterCountIs(expected: number): void; currentSignatureHelpIs(expected: string): void; diff --git a/tests/cases/fourslash/signatureHelpTypeParametersNotVariadic.ts b/tests/cases/fourslash/signatureHelpTypeParametersNotVariadic.ts new file mode 100644 index 00000000000..30b0bac7e71 --- /dev/null +++ b/tests/cases/fourslash/signatureHelpTypeParametersNotVariadic.ts @@ -0,0 +1,8 @@ +/// + +//// declare function f(a: any, ...b: any[]): any; +//// f(1, 2); + +goTo.marker("1"); +verify.signatureHelpArgumentCountIs(0); +verify.signatureHelpCurrentArgumentListIsVariadic(false); \ No newline at end of file