From 3806ee74063849930504bf52f0eb809b0fc6b2d7 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Sun, 2 Sep 2018 21:42:38 +0200 Subject: [PATCH 01/47] Assert CompilerHost.readDiretory for projectReferences with include Fixes: #26785 --- src/compiler/program.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 2bbf17e6098..ea331db57d2 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2811,7 +2811,10 @@ namespace ts { export function parseConfigHostFromCompilerHost(host: CompilerHost): ParseConfigFileHost { return { fileExists: f => host.fileExists(f), - readDirectory: (root, extensions, includes, depth?) => host.readDirectory ? host.readDirectory(root, extensions, includes, depth) : [], + readDirectory(root, extensions, excludes, includes, depth) { + Debug.assertDefined(host.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'"); + return host.readDirectory!(root, extensions, excludes, includes, depth); + }, readFile: f => host.readFile(f), useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(), getCurrentDirectory: () => host.getCurrentDirectory(), From d519e3f21ec36274726c44dab25c9eb48e34953f Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Mon, 3 Sep 2018 09:51:02 +0200 Subject: [PATCH 02/47] hand over to LanguageServiceHost.readDirectory --- src/services/services.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/services/services.ts b/src/services/services.ts index dcc321b00d5..e9af862d002 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1217,6 +1217,10 @@ namespace ts { getDirectories: path => { return host.getDirectories ? host.getDirectories(path) : []; }, + readDirectory(path, extensions, exclude, include, depth) { + Debug.assertDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'"); + return host.readDirectory!(path, extensions, exclude, include, depth); + }, onReleaseOldSourceFile, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames: host.hasChangedAutomaticTypeDirectiveNames From aaa723e2d2ee393331ac9d8eba29d66b80f415fe Mon Sep 17 00:00:00 2001 From: Minh Nguyen Date: Tue, 4 Sep 2018 09:02:16 +0100 Subject: [PATCH 03/47] Enable allowSyntheticDefaultImports if esModuleInterop is enabled Fixes #26193. --- src/compiler/utilities.ts | 5 ++--- ...leInteropEnablesSyntheticDefaultImports.js | 15 +++++++++++++++ ...eropEnablesSyntheticDefaultImports.symbols | 18 ++++++++++++++++++ ...nteropEnablesSyntheticDefaultImports.types | 19 +++++++++++++++++++ ...leInteropEnablesSyntheticDefaultImports.ts | 10 ++++++++++ 5 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.js create mode 100644 tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.symbols create mode 100644 tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.types create mode 100644 tests/cases/compiler/esModuleInteropEnablesSyntheticDefaultImports.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index da13fcb4391..f202116cb4b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -7020,9 +7020,8 @@ namespace ts { const moduleKind = getEmitModuleKind(compilerOptions); return compilerOptions.allowSyntheticDefaultImports !== undefined ? compilerOptions.allowSyntheticDefaultImports - : compilerOptions.esModuleInterop - ? moduleKind !== ModuleKind.None && moduleKind < ModuleKind.ES2015 - : moduleKind === ModuleKind.System; + : compilerOptions.esModuleInterop || + moduleKind === ModuleKind.System; } export function getEmitDeclarations(compilerOptions: CompilerOptions): boolean { diff --git a/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.js b/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.js new file mode 100644 index 00000000000..1852c9f65cf --- /dev/null +++ b/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.js @@ -0,0 +1,15 @@ +//// [tests/cases/compiler/esModuleInteropEnablesSyntheticDefaultImports.ts] //// + +//// [a.ts] +import Namespace from "./b"; +export var x = new Namespace.Foo(); + +//// [b.d.ts] +export class Foo { + member: string; +} + + +//// [a.js] +import Namespace from "./b"; +export var x = new Namespace.Foo(); diff --git a/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.symbols b/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.symbols new file mode 100644 index 00000000000..5ee2812ab59 --- /dev/null +++ b/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.symbols @@ -0,0 +1,18 @@ +=== tests/cases/compiler/a.ts === +import Namespace from "./b"; +>Namespace : Symbol(Namespace, Decl(a.ts, 0, 6)) + +export var x = new Namespace.Foo(); +>x : Symbol(x, Decl(a.ts, 1, 10)) +>Namespace.Foo : Symbol(Namespace.Foo, Decl(b.d.ts, 0, 0)) +>Namespace : Symbol(Namespace, Decl(a.ts, 0, 6)) +>Foo : Symbol(Namespace.Foo, Decl(b.d.ts, 0, 0)) + +=== tests/cases/compiler/b.d.ts === +export class Foo { +>Foo : Symbol(Foo, Decl(b.d.ts, 0, 0)) + + member: string; +>member : Symbol(Foo.member, Decl(b.d.ts, 0, 18)) +} + diff --git a/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.types b/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.types new file mode 100644 index 00000000000..c8092331a47 --- /dev/null +++ b/tests/baselines/reference/esModuleInteropEnablesSyntheticDefaultImports.types @@ -0,0 +1,19 @@ +=== tests/cases/compiler/a.ts === +import Namespace from "./b"; +>Namespace : typeof Namespace + +export var x = new Namespace.Foo(); +>x : Namespace.Foo +>new Namespace.Foo() : Namespace.Foo +>Namespace.Foo : typeof Namespace.Foo +>Namespace : typeof Namespace +>Foo : typeof Namespace.Foo + +=== tests/cases/compiler/b.d.ts === +export class Foo { +>Foo : Foo + + member: string; +>member : string +} + diff --git a/tests/cases/compiler/esModuleInteropEnablesSyntheticDefaultImports.ts b/tests/cases/compiler/esModuleInteropEnablesSyntheticDefaultImports.ts new file mode 100644 index 00000000000..29042d8ea9f --- /dev/null +++ b/tests/cases/compiler/esModuleInteropEnablesSyntheticDefaultImports.ts @@ -0,0 +1,10 @@ +// @esModuleInterop: true +// @module: es2015 +// @Filename: a.ts +import Namespace from "./b"; +export var x = new Namespace.Foo(); + +// @Filename: b.d.ts +export class Foo { + member: string; +} From c203c27f00853e99bc68c80295d8d67ae077f279 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Thu, 6 Sep 2018 08:52:53 +0200 Subject: [PATCH 04/47] Error accessing abstract property in constructor of abstract subclass Fixes: #26411 --- src/compiler/checker.ts | 8 +- .../abstractPropertyInConstructor.errors.txt | 35 +++++- .../abstractPropertyInConstructor.js | 72 +++++++++++ .../abstractPropertyInConstructor.symbols | 115 +++++++++++++++++- .../abstractPropertyInConstructor.types | 113 +++++++++++++++++ .../compiler/abstractPropertyInConstructor.ts | 30 +++++ 6 files changed, 362 insertions(+), 11 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ef173a2c667..0a2c8af7f62 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17986,7 +17986,7 @@ namespace ts { // Referencing abstract properties within their own constructors is not allowed if ((flags & ModifierFlags.Abstract) && isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) { const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!); - if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(node, declaringClassDeclaration)) { + if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(node)) { error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!)); // TODO: GH#18217 return false; } @@ -27120,12 +27120,12 @@ namespace ts { return result; } - function isNodeUsedDuringClassInitialization(node: Node, classDeclaration: ClassLikeDeclaration) { + function isNodeUsedDuringClassInitialization(node: Node) { return !!findAncestor(node, element => { - if ((isConstructorDeclaration(element) && nodeIsPresent(element.body) || isPropertyDeclaration(element)) && element.parent === classDeclaration) { + if (isConstructorDeclaration(element) && nodeIsPresent(element.body) || isPropertyDeclaration(element)) { return true; } - else if (element === classDeclaration || isFunctionLikeDeclaration(element)) { + else if (isClassLike(element) || isFunctionLikeDeclaration(element)) { return "quit"; } diff --git a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt index 5337bfc538a..869ec3b1e65 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt +++ b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt @@ -2,9 +2,10 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(4,24): error TS2715: Abstr tests/cases/compiler/abstractPropertyInConstructor.ts(7,18): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor. tests/cases/compiler/abstractPropertyInConstructor.ts(9,14): error TS2715: Abstract property 'cb' in class 'AbstractClass' cannot be accessed in the constructor. tests/cases/compiler/abstractPropertyInConstructor.ts(25,18): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor. +tests/cases/compiler/abstractPropertyInConstructor.ts(39,22): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor. -==== tests/cases/compiler/abstractPropertyInConstructor.ts (4 errors) ==== +==== tests/cases/compiler/abstractPropertyInConstructor.ts (5 errors) ==== abstract class AbstractClass { constructor(str: string, other: AbstractClass) { this.method(parseInt(str)); @@ -45,6 +46,38 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(25,18): error TS2715: Abst } } + abstract class DerivedAbstractClass extends AbstractClass { + cb = (s: string) => {}; + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { + super(str, other); + // there is no implementation of 'prop' in any base class + this.cb(this.prop.toLowerCase()); + ~~~~ +!!! error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor. + + this.method(1); + + // OK, references are to another instance + other.cb(other.prop); + yetAnother.cb(yetAnother.prop); + } + } + + class Implementation extends DerivedAbstractClass { + prop = ""; + cb = (s: string) => {}; + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { + super(str, other, yetAnother); + this.cb(this.prop); + } + + method(n: number) { + this.cb(this.prop + n); + } + } + class User { constructor(a: AbstractClass) { a.prop; diff --git a/tests/baselines/reference/abstractPropertyInConstructor.js b/tests/baselines/reference/abstractPropertyInConstructor.js index 782419ac67b..a2b281760a2 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.js +++ b/tests/baselines/reference/abstractPropertyInConstructor.js @@ -31,6 +31,36 @@ abstract class AbstractClass { } } +abstract class DerivedAbstractClass extends AbstractClass { + cb = (s: string) => {}; + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { + super(str, other); + // there is no implementation of 'prop' in any base class + this.cb(this.prop.toLowerCase()); + + this.method(1); + + // OK, references are to another instance + other.cb(other.prop); + yetAnother.cb(yetAnother.prop); + } +} + +class Implementation extends DerivedAbstractClass { + prop = ""; + cb = (s: string) => {}; + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { + super(str, other, yetAnother); + this.cb(this.prop); + } + + method(n: number) { + this.cb(this.prop + n); + } +} + class User { constructor(a: AbstractClass) { a.prop; @@ -42,6 +72,19 @@ class User { //// [abstractPropertyInConstructor.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + } + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); var AbstractClass = /** @class */ (function () { function AbstractClass(str, other) { var _this = this; @@ -65,6 +108,35 @@ var AbstractClass = /** @class */ (function () { }; return AbstractClass; }()); +var DerivedAbstractClass = /** @class */ (function (_super) { + __extends(DerivedAbstractClass, _super); + function DerivedAbstractClass(str, other, yetAnother) { + var _this = _super.call(this, str, other) || this; + _this.cb = function (s) { }; + // there is no implementation of 'prop' in any base class + _this.cb(_this.prop.toLowerCase()); + _this.method(1); + // OK, references are to another instance + other.cb(other.prop); + yetAnother.cb(yetAnother.prop); + return _this; + } + return DerivedAbstractClass; +}(AbstractClass)); +var Implementation = /** @class */ (function (_super) { + __extends(Implementation, _super); + function Implementation(str, other, yetAnother) { + var _this = _super.call(this, str, other, yetAnother) || this; + _this.prop = ""; + _this.cb = function (s) { }; + _this.cb(_this.prop); + return _this; + } + Implementation.prototype.method = function (n) { + this.cb(this.prop + n); + }; + return Implementation; +}(DerivedAbstractClass)); var User = /** @class */ (function () { function User(a) { a.prop; diff --git a/tests/baselines/reference/abstractPropertyInConstructor.symbols b/tests/baselines/reference/abstractPropertyInConstructor.symbols index 71f897118c8..628ee5c8576 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.symbols +++ b/tests/baselines/reference/abstractPropertyInConstructor.symbols @@ -92,31 +92,134 @@ abstract class AbstractClass { } } +abstract class DerivedAbstractClass extends AbstractClass { +>DerivedAbstractClass : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1)) +>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) + + cb = (s: string) => {}; +>cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59)) +>s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 33, 10)) + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { +>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 35, 16)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 35, 28)) +>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 35, 50)) +>DerivedAbstractClass : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1)) + + super(str, other); +>super : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 35, 16)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 35, 28)) + + // there is no implementation of 'prop' in any base class + this.cb(this.prop.toLowerCase()); +>this.cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59)) +>this : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1)) +>cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59)) +>this.prop.toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) +>this : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) +>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --)) + + this.method(1); +>this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) +>this : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1)) +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) + + // OK, references are to another instance + other.cb(other.prop); +>other.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 35, 28)) +>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) +>other.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 35, 28)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) + + yetAnother.cb(yetAnother.prop); +>yetAnother.cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59)) +>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 35, 50)) +>cb : Symbol(DerivedAbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 32, 59)) +>yetAnother.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) +>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 35, 50)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) + } +} + +class Implementation extends DerivedAbstractClass { +>Implementation : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1)) +>DerivedAbstractClass : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1)) + + prop = ""; +>prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51)) + + cb = (s: string) => {}; +>cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14)) +>s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 50, 10)) + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { +>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 52, 16)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 52, 28)) +>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 52, 50)) +>DerivedAbstractClass : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1)) + + super(str, other, yetAnother); +>super : Symbol(DerivedAbstractClass, Decl(abstractPropertyInConstructor.ts, 30, 1)) +>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 52, 16)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 52, 28)) +>yetAnother : Symbol(yetAnother, Decl(abstractPropertyInConstructor.ts, 52, 50)) + + this.cb(this.prop); +>this.cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14)) +>this : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1)) +>cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14)) +>this.prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51)) +>this : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1)) +>prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51)) + } + + method(n: number) { +>method : Symbol(Implementation.method, Decl(abstractPropertyInConstructor.ts, 55, 5)) +>n : Symbol(n, Decl(abstractPropertyInConstructor.ts, 57, 11)) + + this.cb(this.prop + n); +>this.cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14)) +>this : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1)) +>cb : Symbol(Implementation.cb, Decl(abstractPropertyInConstructor.ts, 49, 14)) +>this.prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51)) +>this : Symbol(Implementation, Decl(abstractPropertyInConstructor.ts, 46, 1)) +>prop : Symbol(Implementation.prop, Decl(abstractPropertyInConstructor.ts, 48, 51)) +>n : Symbol(n, Decl(abstractPropertyInConstructor.ts, 57, 11)) + } +} + class User { ->User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 30, 1)) +>User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 60, 1)) constructor(a: AbstractClass) { ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16)) >AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) a.prop; >a.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16)) >prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) a.cb("hi"); >a.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16)) >cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) a.method(12); >a.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16)) >method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) a.method2(); >a.method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 25, 25)) ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 33, 16)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 63, 16)) >method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 25, 25)) } } diff --git a/tests/baselines/reference/abstractPropertyInConstructor.types b/tests/baselines/reference/abstractPropertyInConstructor.types index 465e0fb2f04..8c8bd40aff0 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.types +++ b/tests/baselines/reference/abstractPropertyInConstructor.types @@ -104,6 +104,119 @@ abstract class AbstractClass { } } +abstract class DerivedAbstractClass extends AbstractClass { +>DerivedAbstractClass : DerivedAbstractClass +>AbstractClass : AbstractClass + + cb = (s: string) => {}; +>cb : (s: string) => void +>(s: string) => {} : (s: string) => void +>s : string + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { +>str : string +>other : AbstractClass +>yetAnother : DerivedAbstractClass + + super(str, other); +>super(str, other) : void +>super : typeof AbstractClass +>str : string +>other : AbstractClass + + // there is no implementation of 'prop' in any base class + this.cb(this.prop.toLowerCase()); +>this.cb(this.prop.toLowerCase()) : void +>this.cb : (s: string) => void +>this : this +>cb : (s: string) => void +>this.prop.toLowerCase() : string +>this.prop.toLowerCase : () => string +>this.prop : string +>this : this +>prop : string +>toLowerCase : () => string + + this.method(1); +>this.method(1) : void +>this.method : (num: number) => void +>this : this +>method : (num: number) => void +>1 : 1 + + // OK, references are to another instance + other.cb(other.prop); +>other.cb(other.prop) : void +>other.cb : (s: string) => void +>other : AbstractClass +>cb : (s: string) => void +>other.prop : string +>other : AbstractClass +>prop : string + + yetAnother.cb(yetAnother.prop); +>yetAnother.cb(yetAnother.prop) : void +>yetAnother.cb : (s: string) => void +>yetAnother : DerivedAbstractClass +>cb : (s: string) => void +>yetAnother.prop : string +>yetAnother : DerivedAbstractClass +>prop : string + } +} + +class Implementation extends DerivedAbstractClass { +>Implementation : Implementation +>DerivedAbstractClass : DerivedAbstractClass + + prop = ""; +>prop : string +>"" : "" + + cb = (s: string) => {}; +>cb : (s: string) => void +>(s: string) => {} : (s: string) => void +>s : string + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { +>str : string +>other : AbstractClass +>yetAnother : DerivedAbstractClass + + super(str, other, yetAnother); +>super(str, other, yetAnother) : void +>super : typeof DerivedAbstractClass +>str : string +>other : AbstractClass +>yetAnother : DerivedAbstractClass + + this.cb(this.prop); +>this.cb(this.prop) : void +>this.cb : (s: string) => void +>this : this +>cb : (s: string) => void +>this.prop : string +>this : this +>prop : string + } + + method(n: number) { +>method : (n: number) => void +>n : number + + this.cb(this.prop + n); +>this.cb(this.prop + n) : void +>this.cb : (s: string) => void +>this : this +>cb : (s: string) => void +>this.prop + n : string +>this.prop : string +>this : this +>prop : string +>n : number + } +} + class User { >User : User diff --git a/tests/cases/compiler/abstractPropertyInConstructor.ts b/tests/cases/compiler/abstractPropertyInConstructor.ts index 5ea3569e20d..a665431bb4e 100644 --- a/tests/cases/compiler/abstractPropertyInConstructor.ts +++ b/tests/cases/compiler/abstractPropertyInConstructor.ts @@ -30,6 +30,36 @@ abstract class AbstractClass { } } +abstract class DerivedAbstractClass extends AbstractClass { + cb = (s: string) => {}; + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { + super(str, other); + // there is no implementation of 'prop' in any base class + this.cb(this.prop.toLowerCase()); + + this.method(1); + + // OK, references are to another instance + other.cb(other.prop); + yetAnother.cb(yetAnother.prop); + } +} + +class Implementation extends DerivedAbstractClass { + prop = ""; + cb = (s: string) => {}; + + constructor(str: string, other: AbstractClass, yetAnother: DerivedAbstractClass) { + super(str, other, yetAnother); + this.cb(this.prop); + } + + method(n: number) { + this.cb(this.prop + n); + } +} + class User { constructor(a: AbstractClass) { a.prop; From 78d221993b2c4c011834e094d9581acdc5cd4ef4 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Mon, 17 Sep 2018 14:41:48 +0200 Subject: [PATCH 05/47] fix getExtendedConfig in commandLineParser * remove invalid assertion * fix invalid array spread on possibly undefined value * only add unique files to extendedSourceFiles, preventing the array from growing infinitely --- src/compiler/commandLineParser.ts | 17 ++++++++++++----- .../unittests/configurationExtension.ts | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 05113f812db..14925c86354 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1993,7 +1993,7 @@ namespace ts { if (ownConfig.extendedConfigPath) { // copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios. resolutionStack = resolutionStack.concat([resolvedPath]); - const extendedConfig = getExtendedConfig(sourceFile!, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors); + const extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors); if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) { const baseRaw = extendedConfig.raw; const raw = ownConfig.raw; @@ -2134,7 +2134,7 @@ namespace ts { } function getExtendedConfig( - sourceFile: TsConfigSourceFile, + sourceFile: TsConfigSourceFile | undefined, extendedConfigPath: string, host: ParseConfigHost, basePath: string, @@ -2143,7 +2143,12 @@ namespace ts { ): ParsedTsconfig | undefined { const extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path)); if (sourceFile) { - (sourceFile.extendedSourceFiles || (sourceFile.extendedSourceFiles = [])).push(extendedResult.fileName); + if (sourceFile.extendedSourceFiles) { + pushIfUnique(sourceFile.extendedSourceFiles, extendedResult.fileName); + } + else { + sourceFile.extendedSourceFiles = [extendedResult.fileName]; + } } if (extendedResult.parseDiagnostics.length) { errors.push(...extendedResult.parseDiagnostics); @@ -2153,8 +2158,10 @@ namespace ts { const extendedDirname = getDirectoryPath(extendedConfigPath); const extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname, getBaseFileName(extendedConfigPath), resolutionStack, errors); - if (sourceFile) { - sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles!); + if (sourceFile && extendedResult.extendedSourceFiles) { + for (const extended of extendedResult.extendedSourceFiles) { + pushIfUnique(sourceFile.extendedSourceFiles!, extended); + } } if (isSuccessfulParsedTsconfig(extendedConfig)) { diff --git a/src/testRunner/unittests/configurationExtension.ts b/src/testRunner/unittests/configurationExtension.ts index 012b8e0d2fa..b9567b3b54d 100644 --- a/src/testRunner/unittests/configurationExtension.ts +++ b/src/testRunner/unittests/configurationExtension.ts @@ -244,6 +244,20 @@ namespace ts { }, [ combinePaths(basePath, "main.ts") ]); + + it("adds extendedSourceFiles only once", () => { + const sourceFile = readJsonConfigFile("configs/fourth.json", (path) => host.readFile(path)); + const dir = combinePaths(basePath, "configs"); + const expected = [ + combinePaths(dir, "third.json"), + combinePaths(dir, "second.json"), + combinePaths(dir, "base.json"), + ]; + parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json"); + assert.deepEqual(sourceFile.extendedSourceFiles, expected); + parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json"); + assert.deepEqual(sourceFile.extendedSourceFiles, expected); + }); }); }); }); From acb8b1f65fbb59510c007586307ee3c9206c0b65 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 17 Sep 2018 09:06:26 -0700 Subject: [PATCH 06/47] Correct falsiness for {} empty object type --- src/compiler/checker.ts | 51 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 11f279d27d5..99bbd58e6b3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -601,6 +601,8 @@ namespace ts { FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy, NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy, + EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull), + EmptyObjectFacts = All, } const typeofEQFacts = createMapFromTemplate({ @@ -11774,8 +11776,12 @@ namespace ts { const simplified = getSimplifiedType((target).type); const constraint = simplified !== (target).type ? simplified : getConstraintOfType((target).type); if (constraint) { - if (result = isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors)) { - return result; + // We require Ternary.True here such that circular constraints don't cause + // false positives. For example, given 'T extends { [K in keyof T]: string }', + // 'keyof T' has itself as its constraint and produces a Ternary.Maybe when + // related to other types. + if (isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors) === Ternary.True) { + return Ternary.True; } } } @@ -14169,9 +14175,11 @@ namespace ts { (type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts; } if (flags & TypeFlags.Object) { - return isFunctionObjectType(type) ? - strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts : - strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; + return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type) ? + strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts : + isFunctionObjectType(type) ? + strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts : + strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; } if (flags & (TypeFlags.Void | TypeFlags.Undefined)) { return TypeFacts.UndefinedFacts; @@ -15083,23 +15091,24 @@ namespace ts { return getTypeWithFacts(assumeTrue ? mapType(type, narrowTypeForTypeof) : type, facts); function narrowTypeForTypeof(type: Type) { - if (assumeTrue && !(type.flags & TypeFlags.Union)) { - if (type.flags & TypeFlags.Unknown && literal.text === "object") { - return getUnionType([nonPrimitiveType, nullType]); + if (type.flags & TypeFlags.Unknown && literal.text === "object") { + return getUnionType([nonPrimitiveType, nullType]); + } + // We narrow a non-union type to an exact primitive type if the non-union type + // is a supertype of that primitive type. For example, type 'any' can be narrowed + // to one of the primitive types. + const targetType = literal.text === "function" ? globalFunctionType : typeofTypesByName.get(literal.text); + if (targetType) { + if (isTypeSubtypeOf(type, targetType)) { + return type; } - // We narrow a non-union type to an exact primitive type if the non-union type - // is a supertype of that primitive type. For example, type 'any' can be narrowed - // to one of the primitive types. - const targetType = literal.text === "function" ? globalFunctionType : typeofTypesByName.get(literal.text); - if (targetType) { - if (isTypeSubtypeOf(targetType, type)) { - return isTypeAny(type) ? targetType : getIntersectionType([type, targetType]); // Intersection to handle `string` being a subtype of `keyof T` - } - if (type.flags & TypeFlags.Instantiable) { - const constraint = getBaseConstraintOfType(type) || anyType; - if (isTypeSubtypeOf(targetType, constraint)) { - return getIntersectionType([type, targetType]); - } + if (isTypeSubtypeOf(targetType, type)) { + return targetType; + } + if (type.flags & TypeFlags.Instantiable) { + const constraint = getBaseConstraintOfType(type) || anyType; + if (isTypeSubtypeOf(targetType, constraint)) { + return getIntersectionType([type, targetType]); } } } From 46de5067b038536545dd9d7f956971e9160d15e8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 17 Sep 2018 09:06:38 -0700 Subject: [PATCH 07/47] Fix resulting issue in compiler --- src/services/importTracker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 86bee92eaec..9872b378403 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -385,7 +385,7 @@ namespace ts.FindAllReferences { } /** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */ - function forEachPossibleImportOrExportStatement(sourceFileLike: SourceFileLike, action: (statement: Statement) => T): T | undefined { + function forEachPossibleImportOrExportStatement(sourceFileLike: SourceFileLike, action: (statement: Statement) => T) { return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, statement => // TODO: GH#18217 action(statement) || (isAmbientModuleDeclaration(statement) && forEach(statement.body && statement.body.statements, action))); } From 7cc77105033b6c75debb22e7f072d8ff7eca222c Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 17 Sep 2018 16:10:23 +0000 Subject: [PATCH 08/47] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 20300 ++++++++-------- 1 file changed, 10150 insertions(+), 10150 deletions(-) diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index f46e461c240..1760da2a463 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,10151 +1,10151 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - o -. Por ejemplo, '{0}' o '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - global.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()" en su lugar.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + o -. Por ejemplo, '{0}' o '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + global.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()" en su lugar.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 92c17cebcb86a1b2ca0086af02aa7e93d2731c0c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 17 Sep 2018 09:15:52 -0700 Subject: [PATCH 09/47] Accept new baselines --- tests/baselines/reference/mappedTypes4.types | 2 +- .../reference/recursiveTypeRelations.errors.txt | 9 ++++++++- .../reference/strictTypeofUnionNarrowing.types | 6 +++--- .../typeGuardOfFormTypeOfPrimitiveSubtype.types | 12 ++++++------ 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/tests/baselines/reference/mappedTypes4.types b/tests/baselines/reference/mappedTypes4.types index 039aabb7306..fac8d982e92 100644 --- a/tests/baselines/reference/mappedTypes4.types +++ b/tests/baselines/reference/mappedTypes4.types @@ -45,7 +45,7 @@ function boxify(obj: T): Boxified { } return obj; >obj : any ->obj : never +>obj : T } type A = { a: string }; diff --git a/tests/baselines/reference/recursiveTypeRelations.errors.txt b/tests/baselines/reference/recursiveTypeRelations.errors.txt index 8c5596958c3..e39ca75dab9 100644 --- a/tests/baselines/reference/recursiveTypeRelations.errors.txt +++ b/tests/baselines/reference/recursiveTypeRelations.errors.txt @@ -1,9 +1,12 @@ tests/cases/compiler/recursiveTypeRelations.ts(8,5): error TS2391: Function implementation is missing or not immediately following the declaration. tests/cases/compiler/recursiveTypeRelations.ts(27,38): error TS2304: Cannot find name 'ClassNameObject'. +tests/cases/compiler/recursiveTypeRelations.ts(27,55): error TS2345: Argument of type '(obj: any, key: keyof S) => any' is not assignable to parameter of type '(previousValue: any, currentValue: string, currentIndex: number, array: string[]) => any'. + Types of parameters 'key' and 'currentValue' are incompatible. + Type 'string' is not assignable to type 'keyof S'. tests/cases/compiler/recursiveTypeRelations.ts(27,61): error TS2304: Cannot find name 'ClassNameObject'. -==== tests/cases/compiler/recursiveTypeRelations.ts (3 errors) ==== +==== tests/cases/compiler/recursiveTypeRelations.ts (4 errors) ==== // Repro from #14896 type Attributes = { @@ -35,6 +38,10 @@ tests/cases/compiler/recursiveTypeRelations.ts(27,61): error TS2304: Cannot find return Object.keys(arg).reduce((obj: ClassNameObject, key: keyof S) => { ~~~~~~~~~~~~~~~ !!! error TS2304: Cannot find name 'ClassNameObject'. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '(obj: any, key: keyof S) => any' is not assignable to parameter of type '(previousValue: any, currentValue: string, currentIndex: number, array: string[]) => any'. +!!! error TS2345: Types of parameters 'key' and 'currentValue' are incompatible. +!!! error TS2345: Type 'string' is not assignable to type 'keyof S'. ~~~~~~~~~~~~~~~ !!! error TS2304: Cannot find name 'ClassNameObject'. const exportedClassName = styles[key]; diff --git a/tests/baselines/reference/strictTypeofUnionNarrowing.types b/tests/baselines/reference/strictTypeofUnionNarrowing.types index 3039ece15d6..1ec44e14ff0 100644 --- a/tests/baselines/reference/strictTypeofUnionNarrowing.types +++ b/tests/baselines/reference/strictTypeofUnionNarrowing.types @@ -12,7 +12,7 @@ function stringify1(anything: { toString(): string } | undefined): string { >"string" : "string" >anything.toUpperCase() : string >anything.toUpperCase : () => string ->anything : { toString(): string; } & string +>anything : string >toUpperCase : () => string >"" : "" } @@ -29,7 +29,7 @@ function stringify2(anything: {} | undefined): string { >"string" : "string" >anything.toUpperCase() : string >anything.toUpperCase : () => string ->anything : string & {} +>anything : string >toUpperCase : () => string >"" : "" } @@ -64,7 +64,7 @@ function stringify4(anything: { toString?(): string } | undefined): string { >"string" : "string" >anything.toUpperCase() : string >anything.toUpperCase : () => string ->anything : {} & string +>anything : string >toUpperCase : () => string >"" : "" } diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types index 6510b73d44d..4787c07d758 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types @@ -14,7 +14,7 @@ if (typeof a === "number") { let c: number = a; >c : number ->a : number & {} +>a : number } if (typeof a === "string") { >typeof a === "string" : boolean @@ -24,7 +24,7 @@ if (typeof a === "string") { let c: string = a; >c : string ->a : string & {} +>a : string } if (typeof a === "boolean") { >typeof a === "boolean" : boolean @@ -34,7 +34,7 @@ if (typeof a === "boolean") { let c: boolean = a; >c : boolean ->a : (false & {}) | (true & {}) +>a : boolean } if (typeof b === "number") { @@ -45,7 +45,7 @@ if (typeof b === "number") { let c: number = b; >c : number ->b : { toString(): string; } & number +>b : number } if (typeof b === "string") { >typeof b === "string" : boolean @@ -55,7 +55,7 @@ if (typeof b === "string") { let c: string = b; >c : string ->b : { toString(): string; } & string +>b : string } if (typeof b === "boolean") { >typeof b === "boolean" : boolean @@ -65,6 +65,6 @@ if (typeof b === "boolean") { let c: boolean = b; >c : boolean ->b : ({ toString(): string; } & false) | ({ toString(): string; } & true) +>b : boolean } From f9072621a99f3708320e898cea25fe17705aca01 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 09:48:19 -0700 Subject: [PATCH 10/47] Run callback as expression statement when no arg to assign to exists --- .../codefixes/convertToAsyncFunction.ts | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 8bd8341264a..bcc02a23e65 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -234,9 +234,7 @@ namespace ts.codefix { if (renameInfo) { const type = checker.getTypeAtLocation(node); - if (type) { - originalType.set(getNodeId(clone).toString(), type); - } + originalType.set(getNodeId(clone).toString(), type); } } @@ -391,9 +389,14 @@ namespace ts.codefix { return [createReturn(getSynthesizedDeepClone(node))]; } - function createVariableDeclarationOrAssignment(prevArgName: SynthIdentifier, rightHandSide: Expression, transformer: Transformer): NodeArray { + function createVariableDeclarationOrAssignment(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): NodeArray { + if (!prevArgName || prevArgName.identifier.text.length === 0) { + // if there's no argName to assign to, there still might be side effects + return createNodeArray([createStatement(rightHandSide)]); + } if (prevArgName.types.length < prevArgName.numberOfAssignmentsOriginal) { + // if the variable has already been declared, we don't need "let" or "const" return createNodeArray([createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))]); } @@ -404,15 +407,13 @@ namespace ts.codefix { // should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts function getTransformationBody(func: Node, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier, parent: CallExpression, transformer: Transformer): NodeArray { - const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0; const hasArgName = argName && argName.identifier.text.length > 0; const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString()); switch (func.kind) { case SyntaxKind.NullKeyword: // do not produce a transformed statement for a null argument break; - case SyntaxKind.Identifier: - // identifier includes undefined + case SyntaxKind.Identifier: // identifier includes undefined if (!hasArgName) break; const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, [argName.identifier]); @@ -420,13 +421,18 @@ namespace ts.codefix { return createNodeArray([createReturn(synthCall)]); } - if (!hasPrevArgName) break; - - const type = transformer.originalTypeMap.get(getNodeId(func).toString()); - const callSignatures = type && transformer.checker.getSignaturesOfType(type, SignatureKind.Call); - const returnType = callSignatures && callSignatures[0].getReturnType(); - const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, createAwait(synthCall), transformer); - prevArgName!.types.push(returnType!); + const type = transformer.originalTypeMap.get(getNodeId(func).toString()) || transformer.checker.getTypeAtLocation(func); + const callSignatures = transformer.checker.getSignaturesOfType(type, SignatureKind.Call); + if (!callSignatures.length) { + // if identifier in handler has no call signatures, it's invalid + codeActionSucceeded = false; + break; + } + const returnType = callSignatures[0].getReturnType(); + const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName, createAwait(synthCall), transformer); + if (prevArgName) { + prevArgName.types.push(returnType); + } return varDeclOrAssignment; case SyntaxKind.FunctionDeclaration: @@ -462,11 +468,13 @@ namespace ts.codefix { return createNodeArray(innerCbBody); } - if (hasPrevArgName && !shouldReturn) { + if (!shouldReturn) { const type = transformer.checker.getTypeAtLocation(func); const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType(); - const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, getSynthesizedDeepClone(funcBody) as Expression, transformer); - prevArgName!.types.push(returnType); + const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName, getSynthesizedDeepClone(funcBody) as Expression, transformer); + if (prevArgName) { + prevArgName.types.push(returnType); + } return varDeclOrAssignment; } else { @@ -474,7 +482,7 @@ namespace ts.codefix { } } default: - // We've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code. + // If no cases apply, we've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code. codeActionSucceeded = false; break; } From 0016fd72f749f25561a4d70ad36978d48b3505c2 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 09:48:24 -0700 Subject: [PATCH 11/47] Add test --- .../unittests/convertToAsyncFunction.ts | 9 +++++++++ ...oAsyncFunction_runEffectfulContinuation.js | 19 +++++++++++++++++++ ...oAsyncFunction_runEffectfulContinuation.ts | 19 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.ts diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index b58c698effd..7c138756502 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -1181,6 +1181,15 @@ function [#|f|]() { function [#|f|]() { return Promise.resolve().then(f ? (x => x) : (y => y)).then(q => q); } +`); + + _testConvertToAsyncFunction("convertToAsyncFunction_runEffectfulContinuation", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(res).then(_ => console.log("done")); +} +function res(result) { + return Promise.resolve().then(x => console.log(result)); +} `); }); diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.js new file mode 100644 index 00000000000..bebd01f235a --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.js @@ -0,0 +1,19 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(res).then(_ => console.log("done")); +} +function res(result) { + return Promise.resolve().then(x => console.log(result)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const result = await fetch('https://typescriptlang.org'); + await res(result); + return console.log("done"); +} +function res(result) { + return Promise.resolve().then(x => console.log(result)); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.ts new file mode 100644 index 00000000000..bebd01f235a --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.ts @@ -0,0 +1,19 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(res).then(_ => console.log("done")); +} +function res(result) { + return Promise.resolve().then(x => console.log(result)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const result = await fetch('https://typescriptlang.org'); + await res(result); + return console.log("done"); +} +function res(result) { + return Promise.resolve().then(x => console.log(result)); +} From a57467a317e0cc588d3b38a744df6d943f45e66e Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Sep 2018 10:53:48 -0700 Subject: [PATCH 12/47] Fix bugs: Replace SourceFile if '--noUnusedLabels' changed (#27060) * Fix bugs: Replace SourceFile if '--noUnusedLabels' changed * Use properties on CommandLineOptionBase * Handle "alwaysStrict" and better categorize options * Properly handle "strict" * Code review * fix test --- src/compiler/commandLineParser.ts | 37 ++++++++++++++++ src/compiler/program.ts | 24 ++++------- src/compiler/types.ts | 3 ++ src/compiler/utilities.ts | 34 ++++++--------- src/harness/virtualFileSystemWithWatch.ts | 2 +- src/services/documentRegistry.ts | 8 ++-- .../unittests/reuseProgramStructure.ts | 4 +- src/testRunner/unittests/tscWatchMode.ts | 43 ++++++++++++++----- .../unittests/tsserverProjectSystem.ts | 29 +++++++++++++ 9 files changed, 128 insertions(+), 56 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 05113f812db..76d806fa13c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -172,6 +172,8 @@ namespace ts { es2018: ScriptTarget.ES2018, esnext: ScriptTarget.ESNext, }), + affectsSourceFile: true, + affectsModuleResolution: true, paramType: Diagnostics.VERSION, showInSimplifiedHelpView: true, category: Diagnostics.Basic_Options, @@ -190,6 +192,7 @@ namespace ts { es2015: ModuleKind.ES2015, esnext: ModuleKind.ESNext }), + affectsModuleResolution: true, paramType: Diagnostics.KIND, showInSimplifiedHelpView: true, category: Diagnostics.Basic_Options, @@ -202,6 +205,7 @@ namespace ts { name: "lib", type: libMap }, + affectsModuleResolution: true, showInSimplifiedHelpView: true, category: Diagnostics.Basic_Options, description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation @@ -209,6 +213,7 @@ namespace ts { { name: "allowJs", type: "boolean", + affectsModuleResolution: true, showInSimplifiedHelpView: true, category: Diagnostics.Basic_Options, description: Diagnostics.Allow_javascript_files_to_be_compiled @@ -226,6 +231,7 @@ namespace ts { "react-native": JsxEmit.ReactNative, "react": JsxEmit.React }), + affectsSourceFile: true, paramType: Diagnostics.KIND, showInSimplifiedHelpView: true, category: Diagnostics.Basic_Options, @@ -336,6 +342,7 @@ namespace ts { { name: "noImplicitAny", type: "boolean", + affectsSemanticDiagnostics: true, strictFlag: true, showInSimplifiedHelpView: true, category: Diagnostics.Strict_Type_Checking_Options, @@ -344,6 +351,7 @@ namespace ts { { name: "strictNullChecks", type: "boolean", + affectsSemanticDiagnostics: true, strictFlag: true, showInSimplifiedHelpView: true, category: Diagnostics.Strict_Type_Checking_Options, @@ -352,6 +360,7 @@ namespace ts { { name: "strictFunctionTypes", type: "boolean", + affectsSemanticDiagnostics: true, strictFlag: true, showInSimplifiedHelpView: true, category: Diagnostics.Strict_Type_Checking_Options, @@ -360,6 +369,7 @@ namespace ts { { name: "strictPropertyInitialization", type: "boolean", + affectsSemanticDiagnostics: true, strictFlag: true, showInSimplifiedHelpView: true, category: Diagnostics.Strict_Type_Checking_Options, @@ -368,6 +378,7 @@ namespace ts { { name: "noImplicitThis", type: "boolean", + affectsSemanticDiagnostics: true, strictFlag: true, showInSimplifiedHelpView: true, category: Diagnostics.Strict_Type_Checking_Options, @@ -376,6 +387,7 @@ namespace ts { { name: "alwaysStrict", type: "boolean", + affectsSourceFile: true, strictFlag: true, showInSimplifiedHelpView: true, category: Diagnostics.Strict_Type_Checking_Options, @@ -410,6 +422,7 @@ namespace ts { { name: "noFallthroughCasesInSwitch", type: "boolean", + affectsBindDiagnostics: true, affectsSemanticDiagnostics: true, showInSimplifiedHelpView: true, category: Diagnostics.Additional_Checks, @@ -423,6 +436,7 @@ namespace ts { node: ModuleResolutionKind.NodeJs, classic: ModuleResolutionKind.Classic, }), + affectsModuleResolution: true, paramType: Diagnostics.STRATEGY, category: Diagnostics.Module_Resolution_Options, description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, @@ -430,6 +444,7 @@ namespace ts { { name: "baseUrl", type: "string", + affectsModuleResolution: true, isFilePath: true, category: Diagnostics.Module_Resolution_Options, description: Diagnostics.Base_directory_to_resolve_non_absolute_module_names @@ -439,6 +454,7 @@ namespace ts { // use type = object to copy the value as-is name: "paths", type: "object", + affectsModuleResolution: true, isTSConfigOnly: true, category: Diagnostics.Module_Resolution_Options, description: Diagnostics.A_series_of_entries_which_re_map_imports_to_lookup_locations_relative_to_the_baseUrl @@ -454,6 +470,7 @@ namespace ts { type: "string", isFilePath: true }, + affectsModuleResolution: true, category: Diagnostics.Module_Resolution_Options, description: Diagnostics.List_of_root_folders_whose_combined_content_represents_the_structure_of_the_project_at_runtime }, @@ -465,6 +482,7 @@ namespace ts { type: "string", isFilePath: true }, + affectsModuleResolution: true, category: Diagnostics.Module_Resolution_Options, description: Diagnostics.List_of_folders_to_include_type_definitions_from }, @@ -475,6 +493,7 @@ namespace ts { name: "types", type: "string" }, + affectsModuleResolution: true, showInSimplifiedHelpView: true, category: Diagnostics.Module_Resolution_Options, description: Diagnostics.Type_declaration_files_to_be_included_in_compilation @@ -633,12 +652,14 @@ namespace ts { { name: "noLib", type: "boolean", + affectsModuleResolution: true, category: Diagnostics.Advanced_Options, description: Diagnostics.Do_not_include_the_default_library_file_lib_d_ts }, { name: "noResolve", type: "boolean", + affectsModuleResolution: true, category: Diagnostics.Advanced_Options, description: Diagnostics.Do_not_add_triple_slash_references_or_imported_modules_to_the_list_of_compiled_files }, @@ -651,6 +672,7 @@ namespace ts { { name: "disableSizeLimit", type: "boolean", + affectsSourceFile: true, category: Diagnostics.Advanced_Options, description: Diagnostics.Disable_size_limitations_on_JavaScript_projects }, @@ -696,6 +718,7 @@ namespace ts { { name: "allowUnusedLabels", type: "boolean", + affectsBindDiagnostics: true, affectsSemanticDiagnostics: true, category: Diagnostics.Advanced_Options, description: Diagnostics.Do_not_report_errors_on_unused_labels @@ -703,6 +726,7 @@ namespace ts { { name: "allowUnreachableCode", type: "boolean", + affectsBindDiagnostics: true, affectsSemanticDiagnostics: true, category: Diagnostics.Advanced_Options, description: Diagnostics.Do_not_report_errors_on_unreachable_code @@ -730,6 +754,7 @@ namespace ts { { name: "maxNodeModuleJsDepth", type: "number", + // TODO: GH#27108 affectsModuleResolution: true, category: Diagnostics.Advanced_Options, description: Diagnostics.The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files }, @@ -759,6 +784,18 @@ namespace ts { } ]; + /* @internal */ + export const semanticDiagnosticsOptionDeclarations: ReadonlyArray = + optionDeclarations.filter(option => !!option.affectsSemanticDiagnostics); + + /* @internal */ + export const moduleResolutionOptionDeclarations: ReadonlyArray = + optionDeclarations.filter(option => !!option.affectsModuleResolution); + + /* @internal */ + export const sourceFileAffectingCompilerOptions: ReadonlyArray = optionDeclarations.filter(option => + !!option.affectsSourceFile || !!option.affectsModuleResolution || !!option.affectsBindDiagnostics); + /* @internal */ export const buildOpts: CommandLineOption[] = [ ...commonOptionsWithBuild, diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 22d202596c1..ffe07c4cbc1 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -496,23 +496,15 @@ namespace ts { } /** - * Determined if source file needs to be re-created even if its text hasn't changed + * Determine if source file needs to be re-created even if its text hasn't changed */ - function shouldProgramCreateNewSourceFiles(program: Program | undefined, newOptions: CompilerOptions) { - // If any of these options change, we can't reuse old source file even if version match - // The change in options like these could result in change in syntax tree change - const oldOptions = program && program.getCompilerOptions(); - return oldOptions && ( - oldOptions.target !== newOptions.target || - oldOptions.module !== newOptions.module || - oldOptions.moduleResolution !== newOptions.moduleResolution || - oldOptions.noResolve !== newOptions.noResolve || - oldOptions.jsx !== newOptions.jsx || - oldOptions.allowJs !== newOptions.allowJs || - oldOptions.disableSizeLimit !== newOptions.disableSizeLimit || - oldOptions.baseUrl !== newOptions.baseUrl || - !equalOwnProperties(oldOptions.paths, newOptions.paths) - ); + function shouldProgramCreateNewSourceFiles(program: Program | undefined, newOptions: CompilerOptions): boolean { + if (!program) return false; + // If any compiler options change, we can't reuse old source file even if version match + // The change in options like these could result in change in syntax tree or `sourceFile.bindDiagnostics`. + const oldOptions = program.getCompilerOptions(); + return !!sourceFileAffectingCompilerOptions.some(option => + !isJsonEqual(getCompilerOptionValue(oldOptions, option), getCompilerOptionValue(newOptions, option))); } function createCreateProgramOptions(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): CreateProgramOptions { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a5e06c7304b..df267415bc4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4569,6 +4569,9 @@ namespace ts { showInSimplifiedHelpView?: boolean; category?: DiagnosticMessage; strictFlag?: true; // true if the option is one of the flag under strict + affectsSourceFile?: true; // true if we should recreate SourceFiles after this option changes + affectsModuleResolution?: true; // currently same effect as `affectsSourceFile` + affectsBindDiagnostics?: true; // true if this affects binding (currently same effect as `affectsSourceFile`) affectsSemanticDiagnostics?: true; // true if option affects semantic diagnostics } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 907e921b91f..28749ed01e4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -101,22 +101,8 @@ namespace ts { } export function changesAffectModuleResolution(oldOptions: CompilerOptions, newOptions: CompilerOptions): boolean { - return !oldOptions || - (oldOptions.module !== newOptions.module) || - (oldOptions.moduleResolution !== newOptions.moduleResolution) || - (oldOptions.noResolve !== newOptions.noResolve) || - (oldOptions.target !== newOptions.target) || - (oldOptions.noLib !== newOptions.noLib) || - (oldOptions.jsx !== newOptions.jsx) || - (oldOptions.allowJs !== newOptions.allowJs) || - (oldOptions.rootDir !== newOptions.rootDir) || - (oldOptions.configFilePath !== newOptions.configFilePath) || - (oldOptions.baseUrl !== newOptions.baseUrl) || - (oldOptions.maxNodeModuleJsDepth !== newOptions.maxNodeModuleJsDepth) || - !arrayIsEqualTo(oldOptions.lib, newOptions.lib) || - !arrayIsEqualTo(oldOptions.typeRoots, newOptions.typeRoots) || - !arrayIsEqualTo(oldOptions.rootDirs, newOptions.rootDirs) || - !equalOwnProperties(oldOptions.paths, newOptions.paths); + return oldOptions.configFilePath !== newOptions.configFilePath || moduleResolutionOptionDeclarations.some(o => + !isJsonEqual(getCompilerOptionValue(oldOptions, o), getCompilerOptionValue(newOptions, o))); } /** @@ -7106,13 +7092,13 @@ namespace ts { return compilerOptions[flag] === undefined ? !!compilerOptions.strict : !!compilerOptions[flag]; } - export function compilerOptionsAffectSemanticDiagnostics(newOptions: CompilerOptions, oldOptions: CompilerOptions) { - if (oldOptions === newOptions) { - return false; - } + export function compilerOptionsAffectSemanticDiagnostics(newOptions: CompilerOptions, oldOptions: CompilerOptions): boolean { + return oldOptions !== newOptions && + semanticDiagnosticsOptionDeclarations.some(option => !isJsonEqual(getCompilerOptionValue(oldOptions, option), getCompilerOptionValue(newOptions, option))); + } - return optionDeclarations.some(option => (!!option.strictFlag && getStrictOptionValue(newOptions, option.name as StrictOptionName) !== getStrictOptionValue(oldOptions, option.name as StrictOptionName)) || - (!!option.affectsSemanticDiagnostics && !newOptions[option.name] !== !oldOptions[option.name])); + export function getCompilerOptionValue(options: CompilerOptions, option: CommandLineOption): unknown { + return option.strictFlag ? getStrictOptionValue(options, option.name as StrictOptionName) : options[option.name]; } export function hasZeroOrOneAsteriskCharacter(str: string): boolean { @@ -8380,4 +8366,8 @@ namespace ts { // '/// ' directive. return options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib; } + + export function isJsonEqual(a: unknown, b: unknown): boolean { + return a === b || typeof a === "object" && a !== null && typeof b === "object" && b !== null && equalOwnProperties(a as MapLike, b as MapLike, isJsonEqual); + } } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 57fa33a84c2..7e8241f51b4 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -654,7 +654,7 @@ interface Array {}` invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath)); } - invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, useFileNameInCallback?: boolean) { + private invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, useFileNameInCallback?: boolean) { invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath))!, ({ cb, fileName }) => cb(useFileNameInCallback ? fileName : fileFullPath, eventKind)); } diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 7a21cebb4f3..5720c69be68 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -121,10 +121,6 @@ namespace ts { const buckets = createMap>(); const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); - function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey { - return `_${settings.target}|${settings.module}|${settings.noResolve}|${settings.jsx}|${settings.allowJs}|${settings.baseUrl}|${JSON.stringify(settings.typeRoots)}|${JSON.stringify(settings.rootDirs)}|${JSON.stringify(settings.paths)}`; - } - function getBucketForCompilationSettings(key: DocumentRegistryBucketKey, createIfMissing: boolean): Map { let bucket = buckets.get(key); if (!bucket && createIfMissing) { @@ -273,4 +269,8 @@ namespace ts { getKeyForCompilationSettings }; } + + function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey { + return sourceFileAffectingCompilerOptions.map(option => getCompilerOptionValue(settings, option)).join("|") as DocumentRegistryBucketKey; + } } diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index 3fec096d4fa..e9c5989de07 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -305,10 +305,10 @@ namespace ts { assert.equal(program1.structureIsReused, StructureIsReused.Not); }); - it("fails if rootdir changes", () => { + it("succeeds if rootdir changes", () => { const program1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/b" }); updateProgram(program1, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/c" }, noop); - assert.equal(program1.structureIsReused, StructureIsReused.Not); + assert.equal(program1.structureIsReused, StructureIsReused.Completely); }); it("fails if config path changes", () => { diff --git a/src/testRunner/unittests/tscWatchMode.ts b/src/testRunner/unittests/tscWatchMode.ts index e25d0616abe..f4df3df4721 100644 --- a/src/testRunner/unittests/tscWatchMode.ts +++ b/src/testRunner/unittests/tscWatchMode.ts @@ -443,6 +443,33 @@ namespace ts.tscWatch { checkOutputErrorsIncremental(host, emptyArray); }); + it("Updates diagnostics when '--noUnusedLabels' changes", () => { + const aTs: File = { path: "/a.ts", content: "label: while (1) {}" }; + const files = [libFile, aTs]; + const paths = files.map(f => f.path); + const options = (allowUnusedLabels: boolean) => `{ "compilerOptions": { "allowUnusedLabels": ${allowUnusedLabels} } }`; + const tsconfig: File = { path: "/tsconfig.json", content: options(/*allowUnusedLabels*/ true) }; + + const host = createWatchedSystem([...files, tsconfig]); + const watch = createWatchOfConfigFile(tsconfig.path, host); + + checkProgramActualFiles(watch(), paths); + checkOutputErrorsInitial(host, emptyArray); + + host.modifyFile(tsconfig.path, options(/*allowUnusedLabels*/ false)); + host.checkTimeoutQueueLengthAndRun(1); // reload the configured project + + checkProgramActualFiles(watch(), paths); + checkOutputErrorsIncremental(host, [ + getDiagnosticOfFileFromProgram(watch(), aTs.path, 0, "label".length, Diagnostics.Unused_label), + ]); + + host.modifyFile(tsconfig.path, options(/*allowUnusedLabels*/ true)); + host.checkTimeoutQueueLengthAndRun(1); // reload the configured project + checkProgramActualFiles(watch(), paths); + checkOutputErrorsIncremental(host, emptyArray); + }); + it("files explicitly excluded in config file", () => { const configFile: File = { path: "/a/b/tsconfig.json", @@ -1190,7 +1217,7 @@ namespace ts.tscWatch { host.reloadFS(files); host.runQueuedTimeoutCallbacks(); checkProgramActualFiles(watch(), files.map(file => file.path)); - checkOutputErrorsIncremental(host, []); + checkOutputErrorsIncremental(host, emptyArray); }); it("watched files when file is deleted and new file is added as part of change", () => { @@ -1322,12 +1349,10 @@ export class B path: `${currentDirectory}/a.ts`, content: `declare function foo(): null | { hello: any }; foo().hello` - }; - const compilerOptions: CompilerOptions = { }; const config: File = { path: `${currentDirectory}/tsconfig.json`, - content: JSON.stringify({ compilerOptions }) + content: JSON.stringify({ compilerOptions: {} }) }; const files = [aFile, config, libFile]; const host = createWatchedSystem(files, { currentDirectory }); @@ -1335,8 +1360,7 @@ foo().hello` checkProgramActualFiles(watch(), [aFile.path, libFile.path]); checkOutputErrorsInitial(host, emptyArray); const modifiedTimeOfAJs = host.getModifiedTime(`${currentDirectory}/a.js`); - compilerOptions.strictNullChecks = true; - host.writeFile(config.path, JSON.stringify({ compilerOptions })); + host.writeFile(config.path, JSON.stringify({ compilerOptions: { strictNullChecks: true } })); host.runQueuedTimeoutCallbacks(); const expectedStrictNullErrors = [ getDiagnosticOfFileFromProgram(watch(), aFile.path, aFile.content.lastIndexOf("foo()"), 5, Diagnostics.Object_is_possibly_null) @@ -1344,15 +1368,12 @@ foo().hello` checkOutputErrorsIncremental(host, expectedStrictNullErrors); // File a need not be rewritten assert.equal(host.getModifiedTime(`${currentDirectory}/a.js`), modifiedTimeOfAJs); - compilerOptions.strict = true; - delete (compilerOptions.strictNullChecks); - host.writeFile(config.path, JSON.stringify({ compilerOptions })); + host.writeFile(config.path, JSON.stringify({ compilerOptions: { strict: true, alwaysStrict: false } })); // Avoid changing 'alwaysStrict' or must re-bind host.runQueuedTimeoutCallbacks(); checkOutputErrorsIncremental(host, expectedStrictNullErrors); // File a need not be rewritten assert.equal(host.getModifiedTime(`${currentDirectory}/a.js`), modifiedTimeOfAJs); - delete (compilerOptions.strict); - host.writeFile(config.path, JSON.stringify({ compilerOptions })); + host.writeFile(config.path, JSON.stringify({ compilerOptions: {} })); host.runQueuedTimeoutCallbacks(); checkOutputErrorsIncremental(host, emptyArray); // File a need not be rewritten diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index ed130f6772b..b9ffc0c0153 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -10180,6 +10180,35 @@ declare class TestLib { }); }); + describe("tsserverProjectSystem config file change", () => { + it("Updates diagnostics when '--noUnusedLabels' changes", () => { + const aTs: File = { path: "/a.ts", content: "label: while (1) {}" }; + const options = (allowUnusedLabels: boolean) => `{ "compilerOptions": { "allowUnusedLabels": ${allowUnusedLabels} } }`; + const tsconfig: File = { path: "/tsconfig.json", content: options(/*allowUnusedLabels*/ true) }; + + const host = createServerHost([aTs, tsconfig]); + const session = createSession(host); + openFilesForSession([aTs], session); + + host.modifyFile(tsconfig.path, options(/*allowUnusedLabels*/ false)); + host.runQueuedTimeoutCallbacks(); + + const response = executeSessionRequest(session, protocol.CommandTypes.SemanticDiagnosticsSync, { file: aTs.path }) as protocol.Diagnostic[] | undefined; + assert.deepEqual(response, [ + { + start: { line: 1, offset: 1 }, + end: { line: 1, offset: 1 + "label".length }, + text: "Unused label.", + category: "error", + code: Diagnostics.Unused_label.code, + relatedInformation: undefined, + reportsUnnecessary: true, + source: undefined, + }, + ]); + }); + }); + function makeReferenceItem(file: File, isDefinition: boolean, text: string, lineText: string, options?: SpanFromSubstringOptions): protocol.ReferencesResponseItem { return { ...protocolFileSpanFromSubstring(file, text, options), From e710645bf95ff0cc90d3d13d3c15a9cf1e326ae5 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Sep 2018 11:06:39 -0700 Subject: [PATCH 13/47] Never escape string literals from textChanges (#26971) * Never escape string literals from textChanges * Use `boolean | undefined` --- src/compiler/emitter.ts | 12 ++++++------ src/compiler/types.ts | 3 ++- src/compiler/utilities.ts | 4 ++-- src/services/textChanges.ts | 2 +- .../fourslash/importNameCodeFixNewImportFile0.ts | 4 ++-- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 62dfb46f7c5..fe54402d434 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1041,7 +1041,7 @@ namespace ts { // SyntaxKind.TemplateMiddle // SyntaxKind.TemplateTail function emitLiteral(node: LiteralLikeNode) { - const text = getLiteralTextOfNode(node); + const text = getLiteralTextOfNode(node, printerOptions.neverAsciiEscape); if ((printerOptions.sourceMap || printerOptions.inlineSourceMap) && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { writeLiteral(text); @@ -1532,7 +1532,7 @@ namespace ts { expression = skipPartiallyEmittedExpressions(expression); if (isNumericLiteral(expression)) { // check if numeric literal is a decimal literal that was originally written with a dot - const text = getLiteralTextOfNode(expression); + const text = getLiteralTextOfNode(expression, /*neverAsciiEscape*/ true); return !expression.numericLiteralFlags && !stringContains(text, tokenToString(SyntaxKind.DotToken)!); } @@ -3306,20 +3306,20 @@ namespace ts { return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); } - function getLiteralTextOfNode(node: LiteralLikeNode): string { + function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined): string { if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { const textSourceNode = (node).textSourceNode!; if (isIdentifier(textSourceNode)) { - return getEmitFlags(node) & EmitFlags.NoAsciiEscaping ? + return neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(getTextOfNode(textSourceNode))}"` : `"${escapeNonAsciiString(getTextOfNode(textSourceNode))}"`; } else { - return getLiteralTextOfNode(textSourceNode); + return getLiteralTextOfNode(textSourceNode, neverAsciiEscape); } } - return getLiteralText(node, currentSourceFile); + return getLiteralText(node, currentSourceFile, neverAsciiEscape); } /** diff --git a/src/compiler/types.ts b/src/compiler/types.ts index df267415bc4..e0d027ded22 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4967,7 +4967,7 @@ namespace ts { /* @internal */ export interface EmitNode { annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup. - flags: EmitFlags; // Flags that customize emit + flags: EmitFlags; // Flags that customize emit leadingComments?: SynthesizedComment[]; // Synthesized leading comments trailingComments?: SynthesizedComment[]; // Synthesized trailing comments commentRange?: TextRange; // The text range to use when emitting leading or trailing comments @@ -5327,6 +5327,7 @@ namespace ts { /*@internal*/ inlineSourceMap?: boolean; /*@internal*/ extendedDiagnostics?: boolean; /*@internal*/ onlyPrintJsDocStyle?: boolean; + /*@internal*/ neverAsciiEscape?: boolean; } /* @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 28749ed01e4..6b7cb3d30ee 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -524,14 +524,14 @@ namespace ts { return emitNode && emitNode.flags || 0; } - export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile) { + export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, neverAsciiEscape: boolean | undefined) { // If we don't need to downlevel and we can reach the original source text using // the node's parent reference, then simply get the text as it was originally written. if (!nodeIsSynthesized(node) && node.parent && !(isNumericLiteral(node) && node.numericLiteralFlags & TokenFlags.ContainsSeparator)) { return getSourceTextOfNodeFromSourceFile(sourceFile, node); } - const escapeText = getEmitFlags(node) & EmitFlags.NoAsciiEscaping ? escapeString : escapeNonAsciiString; + const escapeText = neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : escapeNonAsciiString; // If we can't reach the original source text, use the canonical form if it's a number, // or a (possibly escaped) quoted form of the original text if it's string-like. diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 32d6360e90c..99b94c2cc86 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -781,7 +781,7 @@ namespace ts.textChanges { function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLineCharacter: string): { text: string, node: Node } { const writer = new Writer(newLineCharacter); const newLine = newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed; - createPrinter({ newLine }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer); + createPrinter({ newLine, neverAsciiEscape: true }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer); return { text: writer.getText(), node: assignPositionsToNode(node) }; } } diff --git a/tests/cases/fourslash/importNameCodeFixNewImportFile0.ts b/tests/cases/fourslash/importNameCodeFixNewImportFile0.ts index 12566de406d..8d86324a934 100644 --- a/tests/cases/fourslash/importNameCodeFixNewImportFile0.ts +++ b/tests/cases/fourslash/importNameCodeFixNewImportFile0.ts @@ -2,12 +2,12 @@ //// [|f1/*0*/();|] -// @Filename: module.ts +// @Filename: jalapeño.ts //// export function f1() {} //// export var v1 = 5; verify.importFixAtPosition([ -`import { f1 } from "./module"; +`import { f1 } from "./jalapeño"; f1();` ]); From 1b9507ad06417036f2ba63b68dc0071d79ed4ae8 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 11:33:28 -0700 Subject: [PATCH 14/47] Wrap expressions returned from promises in awaits when appropriate --- .../codefixes/convertToAsyncFunction.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index bcc02a23e65..54f8d99f724 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -435,7 +435,6 @@ namespace ts.codefix { } return varDeclOrAssignment; - case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: // Arrow functions with block bodies { } will enter this control flow @@ -457,11 +456,11 @@ namespace ts.codefix { } return shouldReturn ? getSynthesizedDeepClones(createNodeArray(refactoredStmts)) : - removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer.constIdentifiers, seenReturnStatement); + removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer, seenReturnStatement); } else { - const funcBody = (func).body; - const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody as Expression)); + const funcBody = cast((func).body, isExpression); + const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody)); const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName); if (innerCbBody.length > 0) { @@ -471,14 +470,16 @@ namespace ts.codefix { if (!shouldReturn) { const type = transformer.checker.getTypeAtLocation(func); const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType(); - const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName, getSynthesizedDeepClone(funcBody) as Expression, transformer); + const rightHandSide = getSynthesizedDeepClone(funcBody); + const possiblyAwaitedRightHandSide = isPromiseReturningExpression(funcBody, transformer.checker) ? createAwait(rightHandSide) : rightHandSide; + const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName, possiblyAwaitedRightHandSide, transformer); if (prevArgName) { prevArgName.types.push(returnType); } return varDeclOrAssignment; } else { - return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody) as Expression)]); + return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody))]); } } default: @@ -495,13 +496,14 @@ namespace ts.codefix { } - function removeReturns(stmts: NodeArray, prevArgName: Identifier, constIdentifiers: Identifier[], seenReturnStatement: boolean): NodeArray { + function removeReturns(stmts: NodeArray, prevArgName: Identifier, transformer: Transformer, seenReturnStatement: boolean): NodeArray { const ret: Statement[] = []; for (const stmt of stmts) { if (isReturnStatement(stmt)) { if (stmt.expression) { + const possiblyAwaitedExpression = isPromiseReturningExpression(stmt.expression, transformer.checker) ? createAwait(stmt.expression) : stmt.expression; ret.push(createVariableStatement(/*modifiers*/ undefined, - (createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, stmt.expression)], getFlagOfIdentifier(prevArgName, constIdentifiers))))); + (createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers))))); } } else { @@ -512,7 +514,7 @@ namespace ts.codefix { // if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables if (!seenReturnStatement) { ret.push(createVariableStatement(/*modifiers*/ undefined, - (createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, constIdentifiers))))); + (createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers))))); } return createNodeArray(ret); From ad43020c8b8386a81d9766d11d6a46df1ecbd87b Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 11:33:47 -0700 Subject: [PATCH 15/47] Add tests --- .../unittests/convertToAsyncFunction.ts | 26 ++++++++++++++++++- .../convertToAsyncFunction_Scope1.ts | 6 ++--- ...cFunction_callbackReturnsFixablePromise.js | 14 ++++++++++ ...cFunction_callbackReturnsFixablePromise.ts | 14 ++++++++++ ...tToAsyncFunction_callbackReturnsPromise.js | 13 ++++++++++ ...tToAsyncFunction_callbackReturnsPromise.ts | 13 ++++++++++ ...cFunction_callbackReturnsPromiseInBlock.js | 13 ++++++++++ ...cFunction_callbackReturnsPromiseInBlock.ts | 13 ++++++++++ ...ction_callbackReturnsPromiseLastInChain.js | 12 +++++++++ ...ction_callbackReturnsPromiseLastInChain.ts | 12 +++++++++ 10 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsFixablePromise.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsFixablePromise.ts create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromise.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromise.ts create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseInBlock.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseInBlock.ts create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseLastInChain.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseLastInChain.ts diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index 7c138756502..3f8032275f5 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -817,7 +817,7 @@ function [#|f|]() { ); _testConvertToAsyncFunction("convertToAsyncFunction_Scope1", ` function [#|f|]() { - var var1:Promise, var2; + var var1: Response, var2; return fetch('https://typescriptlang.org').then( _ => Promise.resolve().then( res => { var2 = "test"; @@ -1190,6 +1190,30 @@ function [#|f|]() { function res(result) { return Promise.resolve().then(x => console.log(result)); } +`); + + _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromise", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)).then(x => console.log(x + 5)); +} +`); + + _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromiseInBlock", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(s => { return Promise.resolve(s.statusText.length) }).then(x => x + 5); +} +`); + + _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsFixablePromise", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText).then(st => st.length)).then(x => console.log(x + 5)); +} +`); + + _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromiseLastInChain", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)); +} `); }); diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Scope1.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Scope1.ts index c9b9d40b3e3..2ce31ce1dbf 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Scope1.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Scope1.ts @@ -1,7 +1,7 @@ // ==ORIGINAL== function /*[#|*/f/*|]*/() { - var var1:Promise, var2; + var var1: Response, var2; return fetch('https://typescriptlang.org').then( _ => Promise.resolve().then( res => { var2 = "test"; @@ -18,11 +18,11 @@ function /*[#|*/f/*|]*/() { // ==ASYNC FUNCTION::Convert to async function== async function f() { - var var1:Promise, var2; + var var1: Response, var2; await fetch('https://typescriptlang.org'); const res = await Promise.resolve(); var2 = "test"; - const res_1 = fetch("https://microsoft.com"); + const res_1 = await fetch("https://microsoft.com"); const response = var1 === res_1; return res(response); } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsFixablePromise.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsFixablePromise.js new file mode 100644 index 00000000000..09989a79fb5 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsFixablePromise.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText).then(st => st.length)).then(x => console.log(x + 5)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const s = await fetch('https://typescriptlang.org'); + const st = await Promise.resolve(s.statusText); + const x = st.length; + return console.log(x + 5); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsFixablePromise.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsFixablePromise.ts new file mode 100644 index 00000000000..09989a79fb5 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsFixablePromise.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText).then(st => st.length)).then(x => console.log(x + 5)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const s = await fetch('https://typescriptlang.org'); + const st = await Promise.resolve(s.statusText); + const x = st.length; + return console.log(x + 5); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromise.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromise.js new file mode 100644 index 00000000000..31ca7652f7c --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromise.js @@ -0,0 +1,13 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)).then(x => console.log(x + 5)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const s = await fetch('https://typescriptlang.org'); + const x = await Promise.resolve(s.statusText.length); + return console.log(x + 5); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromise.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromise.ts new file mode 100644 index 00000000000..31ca7652f7c --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromise.ts @@ -0,0 +1,13 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)).then(x => console.log(x + 5)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const s = await fetch('https://typescriptlang.org'); + const x = await Promise.resolve(s.statusText.length); + return console.log(x + 5); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseInBlock.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseInBlock.js new file mode 100644 index 00000000000..bde99bcc384 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseInBlock.js @@ -0,0 +1,13 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(s => { return Promise.resolve(s.statusText.length) }).then(x => x + 5); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const s = await fetch('https://typescriptlang.org'); + const x = await Promise.resolve(s.statusText.length); + return x + 5; +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseInBlock.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseInBlock.ts new file mode 100644 index 00000000000..bde99bcc384 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseInBlock.ts @@ -0,0 +1,13 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(s => { return Promise.resolve(s.statusText.length) }).then(x => x + 5); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const s = await fetch('https://typescriptlang.org'); + const x = await Promise.resolve(s.statusText.length); + return x + 5; +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseLastInChain.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseLastInChain.js new file mode 100644 index 00000000000..09f98a62649 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseLastInChain.js @@ -0,0 +1,12 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const s = await fetch('https://typescriptlang.org'); + return Promise.resolve(s.statusText.length); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseLastInChain.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseLastInChain.ts new file mode 100644 index 00000000000..09f98a62649 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_callbackReturnsPromiseLastInChain.ts @@ -0,0 +1,12 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const s = await fetch('https://typescriptlang.org'); + return Promise.resolve(s.statusText.length); +} From aac961e60db0884e74c33571678a40057f04f6f2 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 14 Sep 2018 13:23:07 -0700 Subject: [PATCH 16/47] Builder to use project reference redirects to output in the dependencies instead of source files --- src/compiler/builderState.ts | 13 ++- src/compiler/program.ts | 3 +- src/compiler/tsbuild.ts | 2 +- src/compiler/types.ts | 6 ++ src/harness/virtualFileSystemWithWatch.ts | 7 +- src/testRunner/unittests/tsbuildWatchMode.ts | 92 ++++++++++++++++++-- src/testRunner/unittests/tscWatchMode.ts | 7 ++ 7 files changed, 116 insertions(+), 14 deletions(-) diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 12936e5b2e8..6a7c54d6186 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -88,7 +88,7 @@ namespace ts.BuilderState { function getReferencedFileFromImportedModuleSymbol(symbol: Symbol) { if (symbol.declarations && symbol.declarations[0]) { const declarationSourceFile = getSourceFileOfNode(symbol.declarations[0]); - return declarationSourceFile && declarationSourceFile.path; + return declarationSourceFile && (declarationSourceFile.resolvedPath || declarationSourceFile.path); } } @@ -100,6 +100,13 @@ namespace ts.BuilderState { return symbol && getReferencedFileFromImportedModuleSymbol(symbol); } + /** + * Gets the path to reference file from file name, it could be resolvedPath if present otherwise path + */ + function getReferencedFileFromFileName(program: Program, fileName: string, sourceFileDirectory: Path, getCanonicalFileName: GetCanonicalFileName): Path { + return toPath(program.getProjectReferenceRedirect(fileName) || fileName, sourceFileDirectory, getCanonicalFileName); + } + /** * Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true */ @@ -123,7 +130,7 @@ namespace ts.BuilderState { // Handle triple slash references if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) { for (const referencedFile of sourceFile.referencedFiles) { - const referencedPath = toPath(referencedFile.fileName, sourceFileDirectory, getCanonicalFileName); + const referencedPath = getReferencedFileFromFileName(program, referencedFile.fileName, sourceFileDirectory, getCanonicalFileName); addReferencedFile(referencedPath); } } @@ -136,7 +143,7 @@ namespace ts.BuilderState { } const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217 - const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName); + const typeFilePath = getReferencedFileFromFileName(program, fileName, sourceFileDirectory, getCanonicalFileName); addReferencedFile(typeFilePath); }); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index ffe07c4cbc1..c3f6a98258d 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -758,7 +758,8 @@ namespace ts { getConfigFileParsingDiagnostics, getResolvedModuleWithFailedLookupLocationsFromCache, getProjectReferences, - getResolvedProjectReferences + getResolvedProjectReferences, + getProjectReferenceRedirect }; verifyCompilerOptions(); diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 069aedff751..2bf57c78718 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -862,7 +862,7 @@ namespace ts { if (buildProject) { buildSingleInvalidatedProject(buildProject.project, buildProject.reloadLevel); if (hasPendingInvalidatedProjects()) { - if (!timerToBuildInvalidatedProject) { + if (options.watch && !timerToBuildInvalidatedProject) { scheduleBuildInvalidatedProject(); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e0d027ded22..03a5d2b9ce7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2551,6 +2551,11 @@ namespace ts { fileName: string; /* @internal */ path: Path; text: string; + /** Resolved path can be different from path property, + * when file is included through project reference is mapped to its output instead of source + * in that case resolvedPath = path to output file + * path = input file's path + */ /* @internal */ resolvedPath: Path; /** @@ -2819,6 +2824,7 @@ namespace ts { getProjectReferences(): ReadonlyArray | undefined; getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; + /*@internal*/ getProjectReferenceRedirect(fileName: string): string | undefined; } /* @internal */ diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 7e8241f51b4..43c7c5ba897 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -934,7 +934,12 @@ interface Array {}` const folder = this.fs.get(base) as FsFolder; Debug.assert(isFsFolder(folder)); - this.addFileOrFolderInFolder(folder, file); + if (!this.fs.has(file.path)) { + this.addFileOrFolderInFolder(folder, file); + } + else { + this.modifyFile(path, content); + } } write(message: string) { diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index 672feaa565b..994ec6dce35 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -94,6 +94,7 @@ namespace ts.tscWatch { const ui = subProjectFiles(SubProject.ui); const allFiles: ReadonlyArray = [libFile, ...core, ...logic, ...tests, ...ui]; const testProjectExpectedWatchedFiles = [core[0], core[1], core[2], ...logic, ...tests].map(f => f.path); + const testProjectExpectedWatchedDirectoriesRecursive = [projectPath(SubProject.core), projectPath(SubProject.logic)]; function createSolutionInWatchMode(allFiles: ReadonlyArray, defaultOptions?: BuildOptions, disableConsoleClears?: boolean) { const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation }); @@ -110,7 +111,7 @@ namespace ts.tscWatch { function verifyWatches(host: WatchedSystem) { checkWatchedFiles(host, testProjectExpectedWatchedFiles); checkWatchedDirectories(host, emptyArray, /*recursive*/ false); - checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); + checkWatchedDirectories(host, testProjectExpectedWatchedDirectoriesRecursive, /*recursive*/ true); } it("creates solution in watch mode", () => { @@ -161,7 +162,7 @@ namespace ts.tscWatch { function verifyWatches() { checkWatchedFiles(host, additionalFiles ? testProjectExpectedWatchedFiles.concat(newFile.path) : testProjectExpectedWatchedFiles); checkWatchedDirectories(host, emptyArray, /*recursive*/ false); - checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); + checkWatchedDirectories(host, testProjectExpectedWatchedDirectoriesRecursive, /*recursive*/ true); } } @@ -347,7 +348,7 @@ function myFunc() { return 100; }`); function verifyWatches() { checkWatchedFiles(host, projectFiles.map(f => f.path)); checkWatchedDirectories(host, emptyArray, /*recursive*/ false); - checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); + checkWatchedDirectories(host, testProjectExpectedWatchedDirectoriesRecursive, /*recursive*/ true); } }); @@ -389,12 +390,87 @@ let x: string = 10;`); }); }); - it("tsc-watch works with project references", () => { - // Build the composite project - const host = createSolutionInWatchMode(allFiles); + describe("tsc-watch works with project references", () => { + const coreIndexDts = projectFilePath(SubProject.core, "index.d.ts"); + const coreAnotherModuleDts = projectFilePath(SubProject.core, "anotherModule.d.ts"); + const logicIndexDts = projectFilePath(SubProject.logic, "index.d.ts"); + const expectedWatchedFiles = [core[0], logic[0], ...tests, libFile].map(f => f.path).concat(coreIndexDts, coreAnotherModuleDts, logicIndexDts); + const expectedWatchedDirectoriesRecursive = projectSystem.getTypeRootsFromLocation(projectPath(SubProject.tests)); - createWatchOfConfigFile(tests[0].path, host); - checkOutputErrorsInitial(host, emptyArray); + function createSolution() { + const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation }); + const solutionBuilder = createSolutionBuilder(host, [`${project}/${SubProject.tests}`], {}); + return { host, solutionBuilder }; + } + + function createBuiltSolution() { + const result = createSolution(); + const { host, solutionBuilder } = result; + solutionBuilder.buildAllProjects(); + const outputFileStamps = getOutputFileStamps(host); + for (const stamp of outputFileStamps) { + assert.isDefined(stamp[1], `${stamp[0]} expected to be present`); + } + return result; + } + + function verifyWatches(host: WatchedSystem) { + checkWatchedFilesDetailed(host, expectedWatchedFiles, 1); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesRecursive, 1, /*recursive*/ true); + } + + function createSolutionAndWatchMode() { + // Build the composite project + const { host, solutionBuilder } = createBuiltSolution(); + + // Build in watch mode + const watch = createWatchOfConfigFileReturningBuilder(tests[0].path, host); + checkOutputErrorsInitial(host, emptyArray); + + return { host, solutionBuilder, watch }; + } + + function verifyDependencies(watch: () => BuilderProgram, filePath: string, expected: ReadonlyArray) { + checkArray(`${filePath} dependencies`, watch().getAllDependencies(watch().getSourceFile(filePath)!).map(f => f.toLocaleLowerCase()), expected); + } + + describe("invoking when references are already built", () => { + it("verifies dependencies and watches", () => { + const { host, watch } = createSolutionAndWatchMode(); + + verifyWatches(host); + verifyDependencies(watch, coreIndexDts, [coreIndexDts]); + verifyDependencies(watch, coreAnotherModuleDts, [coreAnotherModuleDts]); + verifyDependencies(watch, logicIndexDts, [logicIndexDts, coreAnotherModuleDts]); + verifyDependencies(watch, tests[1].path, [tests[1].path, coreAnotherModuleDts, logicIndexDts, coreAnotherModuleDts]); + }); + + it("local edit in ts file, result in watch compilation because logic.d.ts is written", () => { + const { host, solutionBuilder } = createSolutionAndWatchMode(); + host.writeFile(logic[1].path, `${logic[1].content} +function foo() { +}`); + solutionBuilder.invalidateProject(`${project}/${SubProject.logic}`); + solutionBuilder.buildInvalidatedProject(); + + host.checkTimeoutQueueLengthAndRun(1); // not ideal, but currently because of d.ts but no new file is written + checkOutputErrorsIncremental(host, emptyArray); + }); + + it("non local edit in ts file, rebuilds in watch compilation", () => { + const { host, solutionBuilder } = createSolutionAndWatchMode(); + host.writeFile(logic[1].path, `${logic[1].content} +export function gfoo() { +}`); + solutionBuilder.invalidateProject(logic[0].path); + solutionBuilder.buildInvalidatedProject(); + + host.checkTimeoutQueueLengthAndRun(1); + checkOutputErrorsIncremental(host, emptyArray); + }); + + }); }); }); } diff --git a/src/testRunner/unittests/tscWatchMode.ts b/src/testRunner/unittests/tscWatchMode.ts index f4df3df4721..c4b7d6adf44 100644 --- a/src/testRunner/unittests/tscWatchMode.ts +++ b/src/testRunner/unittests/tscWatchMode.ts @@ -20,6 +20,13 @@ namespace ts.tscWatch { checkArray(`Program rootFileNames`, program.getRootFileNames(), expectedFiles); } + export function createWatchOfConfigFileReturningBuilder(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) { + const compilerHost = createWatchCompilerHostOfConfigFile(configFileName, {}, host); + compilerHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation; + const watch = createWatchProgram(compilerHost); + return () => watch.getCurrentProgram(); + } + export function createWatchOfConfigFile(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) { const compilerHost = createWatchCompilerHostOfConfigFile(configFileName, {}, host); compilerHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation; From b6129b452ff2e2a409eea01d4232229734f3abeb Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 14 Sep 2018 17:12:22 -0700 Subject: [PATCH 17/47] Fix the project reference verification to include json source file version check --- src/compiler/core.ts | 4 +-- src/compiler/program.ts | 26 +++++++++++--- src/harness/virtualFileSystemWithWatch.ts | 3 +- src/testRunner/unittests/tsbuildWatchMode.ts | 37 ++++++++++++++++---- 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 9eabae70d2e..45b9351759c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -842,7 +842,7 @@ namespace ts { return deduplicateSorted(sort(array, comparer), equalityComparer || comparer); } - export function arrayIsEqualTo(array1: ReadonlyArray | undefined, array2: ReadonlyArray | undefined, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean { + export function arrayIsEqualTo(array1: ReadonlyArray | undefined, array2: ReadonlyArray | undefined, equalityComparer: (a: T, b: T, index: number) => boolean = equateValues): boolean { if (!array1 || !array2) { return array1 === array2; } @@ -852,7 +852,7 @@ namespace ts { } for (let i = 0; i < array1.length; i++) { - if (!equalityComparer(array1[i], array2[i])) { + if (!equalityComparer(array1[i], array2[i], i)) { return false; } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c3f6a98258d..c6fe9370154 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -455,7 +455,7 @@ namespace ts { } // If project references dont match - if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences)) { + if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences, projectReferenceUptoDate)) { return false; } @@ -483,9 +483,27 @@ namespace ts { return true; - function sourceFileNotUptoDate(sourceFile: SourceFile): boolean { - return sourceFile.version !== getSourceVersion(sourceFile.path) || - hasInvalidatedResolution(sourceFile.path); + function sourceFileNotUptoDate(sourceFile: SourceFile) { + return !sourceFileVersionUptoDate(sourceFile) || + hasInvalidatedResolution(sourceFile.resolvedPath || sourceFile.path); + } + + function sourceFileVersionUptoDate(sourceFile: SourceFile) { + return sourceFile.version === getSourceVersion(sourceFile.resolvedPath || sourceFile.path); + } + + function projectReferenceUptoDate(oldRef: ProjectReference, newRef: ProjectReference, index: number) { + if (!projectReferenceIsEqualTo(oldRef, newRef)) { + return false; + } + const oldResolvedRef = program!.getResolvedProjectReferences()![index]; + if (oldResolvedRef) { + // If sourceFile for the oldResolvedRef existed, check the version for uptodate + return sourceFileVersionUptoDate(oldResolvedRef.sourceFile); + } + // In old program, not able to resolve project reference path, + // so if config file doesnt exist, it is uptodate. + return !fileExists(resolveProjectReferencePath(oldRef)); } } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 43c7c5ba897..b85d5aa1c79 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -187,9 +187,10 @@ interface Array {}` } export function checkArray(caption: string, actual: ReadonlyArray, expected: ReadonlyArray) { + checkMapKeys(caption, arrayToMap(actual, identity), expected); assert.equal(actual.length, expected.length, `${caption}: incorrect actual number of files, expected:\r\n${expected.join("\r\n")}\r\ngot: ${actual.join("\r\n")}`); for (const f of expected) { - assert.equal(true, contains(actual, f), `${caption}: expected to find ${f} in ${actual}`); + assert.isTrue(contains(actual, f), `${caption}: expected to find ${f} in ${actual}`); } } diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index 994ec6dce35..f0745a373a0 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -34,6 +34,10 @@ namespace ts.tscWatch { return `${projectPath(subProject)}/${baseFileName.toLowerCase()}`; } + function projectFileName(subProject: SubProject, baseFileName: string) { + return `${projectPath(subProject)}/${baseFileName}`; + } + function projectFile(subProject: SubProject, baseFileName: string): File { return { path: projectFilePath(subProject, baseFileName), @@ -391,10 +395,10 @@ let x: string = 10;`); }); describe("tsc-watch works with project references", () => { - const coreIndexDts = projectFilePath(SubProject.core, "index.d.ts"); - const coreAnotherModuleDts = projectFilePath(SubProject.core, "anotherModule.d.ts"); - const logicIndexDts = projectFilePath(SubProject.logic, "index.d.ts"); - const expectedWatchedFiles = [core[0], logic[0], ...tests, libFile].map(f => f.path).concat(coreIndexDts, coreAnotherModuleDts, logicIndexDts); + const coreIndexDts = projectFileName(SubProject.core, "index.d.ts"); + const coreAnotherModuleDts = projectFileName(SubProject.core, "anotherModule.d.ts"); + const logicIndexDts = projectFileName(SubProject.logic, "index.d.ts"); + const expectedWatchedFiles = [core[0], logic[0], ...tests, libFile].map(f => f.path).concat([coreIndexDts, coreAnotherModuleDts, logicIndexDts].map(f => f.toLowerCase())); const expectedWatchedDirectoriesRecursive = projectSystem.getTypeRootsFromLocation(projectPath(SubProject.tests)); function createSolution() { @@ -432,7 +436,7 @@ let x: string = 10;`); } function verifyDependencies(watch: () => BuilderProgram, filePath: string, expected: ReadonlyArray) { - checkArray(`${filePath} dependencies`, watch().getAllDependencies(watch().getSourceFile(filePath)!).map(f => f.toLocaleLowerCase()), expected); + checkArray(`${filePath} dependencies`, watch().getAllDependencies(watch().getSourceFile(filePath)!), expected); } describe("invoking when references are already built", () => { @@ -447,7 +451,7 @@ let x: string = 10;`); }); it("local edit in ts file, result in watch compilation because logic.d.ts is written", () => { - const { host, solutionBuilder } = createSolutionAndWatchMode(); + const { host, solutionBuilder, watch } = createSolutionAndWatchMode(); host.writeFile(logic[1].path, `${logic[1].content} function foo() { }`); @@ -456,10 +460,11 @@ function foo() { host.checkTimeoutQueueLengthAndRun(1); // not ideal, but currently because of d.ts but no new file is written checkOutputErrorsIncremental(host, emptyArray); + checkProgramActualFiles(watch().getProgram(), [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, logicIndexDts]); }); it("non local edit in ts file, rebuilds in watch compilation", () => { - const { host, solutionBuilder } = createSolutionAndWatchMode(); + const { host, solutionBuilder, watch } = createSolutionAndWatchMode(); host.writeFile(logic[1].path, `${logic[1].content} export function gfoo() { }`); @@ -468,8 +473,26 @@ export function gfoo() { host.checkTimeoutQueueLengthAndRun(1); checkOutputErrorsIncremental(host, emptyArray); + checkProgramActualFiles(watch().getProgram(), [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, logicIndexDts]); }); + it("change in project reference config file builds correctly", () => { + const { host, solutionBuilder, watch } = createSolutionAndWatchMode(); + host.writeFile(logic[0].path, JSON.stringify({ + compilerOptions: { composite: true, declaration: true, declarationDir: "decls" }, + references: [{ path: "../core" }] + })); + solutionBuilder.invalidateProject(logic[0].path, ConfigFileProgramReloadLevel.Full); + solutionBuilder.buildInvalidatedProject(); + + host.checkTimeoutQueueLengthAndRun(1); + checkOutputErrorsIncremental(host, [ + // TODO: #26036 + // The error is reported in d.ts file because it isnt resolved from ts file path, but is resolved from .d.ts file + "sample1/logic/decls/index.d.ts(2,22): error TS2307: Cannot find module '../core/anotherModule'.\n" + ]); + checkProgramActualFiles(watch().getProgram(), [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, projectFilePath(SubProject.logic, "decls/index.d.ts")]); + }); }); }); }); From f71030f011b2918033f529a9ff582622665e8cde Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Mon, 17 Sep 2018 21:24:26 +0200 Subject: [PATCH 18/47] Simply override extendedSourceFiles array --- src/compiler/commandLineParser.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 14925c86354..98f0f586c8b 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -2143,12 +2143,7 @@ namespace ts { ): ParsedTsconfig | undefined { const extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path)); if (sourceFile) { - if (sourceFile.extendedSourceFiles) { - pushIfUnique(sourceFile.extendedSourceFiles, extendedResult.fileName); - } - else { - sourceFile.extendedSourceFiles = [extendedResult.fileName]; - } + sourceFile.extendedSourceFiles = [extendedResult.fileName]; } if (extendedResult.parseDiagnostics.length) { errors.push(...extendedResult.parseDiagnostics); @@ -2159,9 +2154,7 @@ namespace ts { const extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname, getBaseFileName(extendedConfigPath), resolutionStack, errors); if (sourceFile && extendedResult.extendedSourceFiles) { - for (const extended of extendedResult.extendedSourceFiles) { - pushIfUnique(sourceFile.extendedSourceFiles!, extended); - } + sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles); } if (isSuccessfulParsedTsconfig(extendedConfig)) { From a5fd3e91761b27780985bbdb24ce0d7f1b7d15ee Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 17 Sep 2018 12:43:50 -0700 Subject: [PATCH 19/47] Handle out and outFile options correctly in tsbuild --- src/compiler/program.ts | 28 +++++++++++++++++++--------- src/compiler/tsbuild.ts | 11 ++++++----- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c6fe9370154..82ae2aac38b 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -676,8 +676,9 @@ namespace ts { const parsedRef = parseProjectReferenceConfigFile(ref); resolvedProjectReferences!.push(parsedRef); if (parsedRef) { - if (parsedRef.commandLine.options.outFile) { - const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts"); + const out = parsedRef.commandLine.options.outFile || parsedRef.commandLine.options.out; + if (out) { + const dtsOutfile = changeExtension(out, ".d.ts"); processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined); } addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects); @@ -1244,6 +1245,13 @@ namespace ts { } resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives(); resolvedProjectReferences = oldProgram.getResolvedProjectReferences(); + if (resolvedProjectReferences) { + resolvedProjectReferences.forEach(ref => { + if (ref) { + addProjectReferenceRedirects(ref.commandLine, projectReferenceRedirects); + } + }); + } sourceFileToPackageName = oldProgram.sourceFileToPackageName; redirectTargetsMap = oldProgram.redirectTargetsMap; @@ -1299,12 +1307,13 @@ namespace ts { const ref = projectReferences[i]; const resolvedRefOpts = resolvedProjectReferences![i]!.commandLine; if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) { + const out = resolvedRefOpts.options.outFile || resolvedRefOpts.options.out; // Upstream project didn't have outFile set -- skip (error will have been issued earlier) - if (!resolvedRefOpts.options.outFile) continue; + if (!out) continue; - const dtsFilename = changeExtension(resolvedRefOpts.options.outFile, ".d.ts"); - const js = host.readFile(resolvedRefOpts.options.outFile) || `/* Input file ${resolvedRefOpts.options.outFile} was missing */\r\n`; - const jsMapPath = resolvedRefOpts.options.outFile + ".map"; // TODO: try to read sourceMappingUrl comment from the file + const dtsFilename = changeExtension(out, ".d.ts"); + const js = host.readFile(out) || `/* Input file ${out} was missing */\r\n`; + const jsMapPath = out + ".map"; // TODO: try to read sourceMappingUrl comment from the file const jsMap = host.readFile(jsMapPath); const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`; const dtsMapPath = dtsFilename + ".map"; @@ -2446,9 +2455,10 @@ namespace ts { createDiagnosticForReference(i, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path); } if (ref.prepend) { - if (resolvedRefOpts.outFile) { - if (!host.fileExists(resolvedRefOpts.outFile)) { - createDiagnosticForReference(i, Diagnostics.Output_file_0_from_project_1_does_not_exist, resolvedRefOpts.outFile, ref.path); + const out = resolvedRefOpts.outFile || resolvedRefOpts.out; + if (out) { + if (!host.fileExists(out)) { + createDiagnosticForReference(i, Diagnostics.Output_file_0_from_project_1_does_not_exist, out, ref.path); } } else { diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 2bf57c78718..6c3681dbd5c 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -285,16 +285,17 @@ namespace ts { } function getOutFileOutputs(project: ParsedCommandLine): ReadonlyArray { - if (!project.options.outFile) { + const out = project.options.outFile || project.options.out; + if (!out) { return Debug.fail("outFile must be set"); } const outputs: string[] = []; - outputs.push(project.options.outFile); + outputs.push(out); if (project.options.sourceMap) { - outputs.push(`${project.options.outFile}.map`); + outputs.push(`${out}.map`); } if (getEmitDeclarations(project.options)) { - const dts = changeExtension(project.options.outFile, Extension.Dts); + const dts = changeExtension(out, Extension.Dts); outputs.push(dts); if (project.options.declarationMap) { outputs.push(`${dts}.map`); @@ -1248,7 +1249,7 @@ namespace ts { } export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray { - if (project.options.outFile) { + if (project.options.outFile || project.options.out) { return getOutFileOutputs(project); } else { From 989a717b04f3c23d968f727f84d72af039c63f8a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 17 Sep 2018 12:56:39 -0700 Subject: [PATCH 20/47] Definite assignment checking for expando properties (#27128) --- src/compiler/checker.ts | 11 + .../typeFromPropertyAssignment36.errors.txt | 85 +++++++ .../reference/typeFromPropertyAssignment36.js | 144 +++++++++++ .../typeFromPropertyAssignment36.symbols | 178 +++++++++++++ .../typeFromPropertyAssignment36.types | 233 ++++++++++++++++++ .../salsa/typeFromPropertyAssignment36.ts | 73 ++++++ 6 files changed, 724 insertions(+) create mode 100644 tests/baselines/reference/typeFromPropertyAssignment36.errors.txt create mode 100644 tests/baselines/reference/typeFromPropertyAssignment36.js create mode 100644 tests/baselines/reference/typeFromPropertyAssignment36.symbols create mode 100644 tests/baselines/reference/typeFromPropertyAssignment36.types create mode 100644 tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 11f279d27d5..2eae269b1a3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14734,6 +14734,14 @@ namespace ts { // reference 'x.y.z', we may be at an assignment to 'x.y' or 'x'. In that case, // return the declared type. if (containsMatchingReference(reference, node)) { + // A matching dotted name might also be an expando property on a function *expression*, + // in which case we continue control flow analysis back to the function's declaration + if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConst(node))) { + const init = getDeclaredExpandoInitializer(node); + if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) { + return getTypeAtFlowNode(flow.antecedent); + } + } return declaredType; } // Assignment doesn't affect reference @@ -18395,6 +18403,9 @@ namespace ts { } } } + else if (strictNullChecks && prop && prop.valueDeclaration && isPropertyAccessExpression(prop.valueDeclaration) && getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration)) { + assumeUninitialized = true; + } const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType); if (assumeUninitialized && !(getFalsyFlags(propType) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) { error(right, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217 diff --git a/tests/baselines/reference/typeFromPropertyAssignment36.errors.txt b/tests/baselines/reference/typeFromPropertyAssignment36.errors.txt new file mode 100644 index 00000000000..3cd98f56b4b --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment36.errors.txt @@ -0,0 +1,85 @@ +tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts(11,7): error TS2565: Property 'q' is used before being assigned. +tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts(42,3): error TS2565: Property 'q' is used before being assigned. +tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts(64,3): error TS2565: Property 'expando' is used before being assigned. + + +==== tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts (3 errors) ==== + function f(b: boolean) { + function d() { + } + d.e = 12 + d.e + + if (b) { + d.q = false + } + // error d.q might not be assigned + d.q + ~ +!!! error TS2565: Property 'q' is used before being assigned. + if (b) { + d.q = false + } + else { + d.q = true + } + d.q + if (b) { + d.r = 1 + } + else { + d.r = 2 + } + d.r + if (b) { + d.s = 'hi' + } + return d + } + // OK to access possibly-unassigned properties outside the initialising scope + var test = f(true).s + + function d() { + } + d.e = 12 + d.e + + if (!!false) { + d.q = false + } + d.q + ~ +!!! error TS2565: Property 'q' is used before being assigned. + if (!!false) { + d.q = false + } + else { + d.q = true + } + d.q + if (!!false) { + d.r = 1 + } + else { + d.r = 2 + } + d.r + + // test function expressions too + const g = function() { + } + if (!!false) { + g.expando = 1 + } + g.expando // error + ~~~~~~~ +!!! error TS2565: Property 'expando' is used before being assigned. + + if (!!false) { + g.both = 'hi' + } + else { + g.both = 0 + } + g.both + \ No newline at end of file diff --git a/tests/baselines/reference/typeFromPropertyAssignment36.js b/tests/baselines/reference/typeFromPropertyAssignment36.js new file mode 100644 index 00000000000..ae0c2ec244b --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment36.js @@ -0,0 +1,144 @@ +//// [typeFromPropertyAssignment36.ts] +function f(b: boolean) { + function d() { + } + d.e = 12 + d.e + + if (b) { + d.q = false + } + // error d.q might not be assigned + d.q + if (b) { + d.q = false + } + else { + d.q = true + } + d.q + if (b) { + d.r = 1 + } + else { + d.r = 2 + } + d.r + if (b) { + d.s = 'hi' + } + return d +} +// OK to access possibly-unassigned properties outside the initialising scope +var test = f(true).s + +function d() { +} +d.e = 12 +d.e + +if (!!false) { + d.q = false +} +d.q +if (!!false) { + d.q = false +} +else { + d.q = true +} +d.q +if (!!false) { + d.r = 1 +} +else { + d.r = 2 +} +d.r + +// test function expressions too +const g = function() { +} +if (!!false) { + g.expando = 1 +} +g.expando // error + +if (!!false) { + g.both = 'hi' +} +else { + g.both = 0 +} +g.both + + +//// [typeFromPropertyAssignment36.js] +"use strict"; +function f(b) { + function d() { + } + d.e = 12; + d.e; + if (b) { + d.q = false; + } + // error d.q might not be assigned + d.q; + if (b) { + d.q = false; + } + else { + d.q = true; + } + d.q; + if (b) { + d.r = 1; + } + else { + d.r = 2; + } + d.r; + if (b) { + d.s = 'hi'; + } + return d; +} +// OK to access possibly-unassigned properties outside the initialising scope +var test = f(true).s; +function d() { +} +d.e = 12; +d.e; +if (!!false) { + d.q = false; +} +d.q; +if (!!false) { + d.q = false; +} +else { + d.q = true; +} +d.q; +if (!!false) { + d.r = 1; +} +else { + d.r = 2; +} +d.r; +// test function expressions too +var g = function () { +}; +if (!!false) { + g.expando = 1; +} +g.expando; // error +if (!!false) { + g.both = 'hi'; +} +else { + g.both = 0; +} +g.both; diff --git a/tests/baselines/reference/typeFromPropertyAssignment36.symbols b/tests/baselines/reference/typeFromPropertyAssignment36.symbols new file mode 100644 index 00000000000..1c90cf5684c --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment36.symbols @@ -0,0 +1,178 @@ +=== tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts === +function f(b: boolean) { +>f : Symbol(f, Decl(typeFromPropertyAssignment36.ts, 0, 0)) +>b : Symbol(b, Decl(typeFromPropertyAssignment36.ts, 0, 11)) + + function d() { +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) + } + d.e = 12 +>d.e : Symbol(d.e, Decl(typeFromPropertyAssignment36.ts, 2, 5)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>e : Symbol(d.e, Decl(typeFromPropertyAssignment36.ts, 2, 5)) + + d.e +>d.e : Symbol(d.e, Decl(typeFromPropertyAssignment36.ts, 2, 5)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>e : Symbol(d.e, Decl(typeFromPropertyAssignment36.ts, 2, 5)) + + if (b) { +>b : Symbol(b, Decl(typeFromPropertyAssignment36.ts, 0, 11)) + + d.q = false +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) + } + // error d.q might not be assigned + d.q +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) + + if (b) { +>b : Symbol(b, Decl(typeFromPropertyAssignment36.ts, 0, 11)) + + d.q = false +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) + } + else { + d.q = true +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) + } + d.q +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 6, 12), Decl(typeFromPropertyAssignment36.ts, 11, 12), Decl(typeFromPropertyAssignment36.ts, 14, 10)) + + if (b) { +>b : Symbol(b, Decl(typeFromPropertyAssignment36.ts, 0, 11)) + + d.r = 1 +>d.r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 18, 12), Decl(typeFromPropertyAssignment36.ts, 21, 10)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 18, 12), Decl(typeFromPropertyAssignment36.ts, 21, 10)) + } + else { + d.r = 2 +>d.r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 18, 12), Decl(typeFromPropertyAssignment36.ts, 21, 10)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 18, 12), Decl(typeFromPropertyAssignment36.ts, 21, 10)) + } + d.r +>d.r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 18, 12), Decl(typeFromPropertyAssignment36.ts, 21, 10)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 18, 12), Decl(typeFromPropertyAssignment36.ts, 21, 10)) + + if (b) { +>b : Symbol(b, Decl(typeFromPropertyAssignment36.ts, 0, 11)) + + d.s = 'hi' +>d.s : Symbol(d.s, Decl(typeFromPropertyAssignment36.ts, 25, 12)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +>s : Symbol(d.s, Decl(typeFromPropertyAssignment36.ts, 25, 12)) + } + return d +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 0, 24)) +} +// OK to access possibly-unassigned properties outside the initialising scope +var test = f(true).s +>test : Symbol(test, Decl(typeFromPropertyAssignment36.ts, 31, 3)) +>f(true).s : Symbol(d.s, Decl(typeFromPropertyAssignment36.ts, 25, 12)) +>f : Symbol(f, Decl(typeFromPropertyAssignment36.ts, 0, 0)) +>s : Symbol(d.s, Decl(typeFromPropertyAssignment36.ts, 25, 12)) + +function d() { +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +} +d.e = 12 +>d.e : Symbol(d.e, Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>e : Symbol(d.e, Decl(typeFromPropertyAssignment36.ts, 34, 1)) + +d.e +>d.e : Symbol(d.e, Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>e : Symbol(d.e, Decl(typeFromPropertyAssignment36.ts, 34, 1)) + +if (!!false) { + d.q = false +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) +} +d.q +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) + +if (!!false) { + d.q = false +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) +} +else { + d.q = true +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) +} +d.q +>d.q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>q : Symbol(d.q, Decl(typeFromPropertyAssignment36.ts, 38, 14), Decl(typeFromPropertyAssignment36.ts, 42, 14), Decl(typeFromPropertyAssignment36.ts, 45, 6)) + +if (!!false) { + d.r = 1 +>d.r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 49, 14), Decl(typeFromPropertyAssignment36.ts, 52, 6)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 49, 14), Decl(typeFromPropertyAssignment36.ts, 52, 6)) +} +else { + d.r = 2 +>d.r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 49, 14), Decl(typeFromPropertyAssignment36.ts, 52, 6)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 49, 14), Decl(typeFromPropertyAssignment36.ts, 52, 6)) +} +d.r +>d.r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 49, 14), Decl(typeFromPropertyAssignment36.ts, 52, 6)) +>d : Symbol(d, Decl(typeFromPropertyAssignment36.ts, 31, 20), Decl(typeFromPropertyAssignment36.ts, 34, 1)) +>r : Symbol(d.r, Decl(typeFromPropertyAssignment36.ts, 49, 14), Decl(typeFromPropertyAssignment36.ts, 52, 6)) + +// test function expressions too +const g = function() { +>g : Symbol(g, Decl(typeFromPropertyAssignment36.ts, 58, 5)) +} +if (!!false) { + g.expando = 1 +>g.expando : Symbol(g.expando, Decl(typeFromPropertyAssignment36.ts, 60, 14)) +>g : Symbol(g, Decl(typeFromPropertyAssignment36.ts, 58, 5)) +>expando : Symbol(g.expando, Decl(typeFromPropertyAssignment36.ts, 60, 14)) +} +g.expando // error +>g.expando : Symbol(g.expando, Decl(typeFromPropertyAssignment36.ts, 60, 14)) +>g : Symbol(g, Decl(typeFromPropertyAssignment36.ts, 58, 5)) +>expando : Symbol(g.expando, Decl(typeFromPropertyAssignment36.ts, 60, 14)) + +if (!!false) { + g.both = 'hi' +>g.both : Symbol(g.both, Decl(typeFromPropertyAssignment36.ts, 65, 14), Decl(typeFromPropertyAssignment36.ts, 68, 6)) +>g : Symbol(g, Decl(typeFromPropertyAssignment36.ts, 58, 5)) +>both : Symbol(g.both, Decl(typeFromPropertyAssignment36.ts, 65, 14), Decl(typeFromPropertyAssignment36.ts, 68, 6)) +} +else { + g.both = 0 +>g.both : Symbol(g.both, Decl(typeFromPropertyAssignment36.ts, 65, 14), Decl(typeFromPropertyAssignment36.ts, 68, 6)) +>g : Symbol(g, Decl(typeFromPropertyAssignment36.ts, 58, 5)) +>both : Symbol(g.both, Decl(typeFromPropertyAssignment36.ts, 65, 14), Decl(typeFromPropertyAssignment36.ts, 68, 6)) +} +g.both +>g.both : Symbol(g.both, Decl(typeFromPropertyAssignment36.ts, 65, 14), Decl(typeFromPropertyAssignment36.ts, 68, 6)) +>g : Symbol(g, Decl(typeFromPropertyAssignment36.ts, 58, 5)) +>both : Symbol(g.both, Decl(typeFromPropertyAssignment36.ts, 65, 14), Decl(typeFromPropertyAssignment36.ts, 68, 6)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment36.types b/tests/baselines/reference/typeFromPropertyAssignment36.types new file mode 100644 index 00000000000..4eb184fa0bb --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment36.types @@ -0,0 +1,233 @@ +=== tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts === +function f(b: boolean) { +>f : (b: boolean) => { (): void; e: number; q: boolean; r: number; s: string; } +>b : boolean + + function d() { +>d : { (): void; e: number; q: boolean; r: number; s: string; } + } + d.e = 12 +>d.e = 12 : 12 +>d.e : number +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>e : number +>12 : 12 + + d.e +>d.e : number +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>e : number + + if (b) { +>b : boolean + + d.q = false +>d.q = false : false +>d.q : boolean +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>q : boolean +>false : false + } + // error d.q might not be assigned + d.q +>d.q : boolean +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>q : boolean + + if (b) { +>b : boolean + + d.q = false +>d.q = false : false +>d.q : boolean +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>q : boolean +>false : false + } + else { + d.q = true +>d.q = true : true +>d.q : boolean +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>q : boolean +>true : true + } + d.q +>d.q : boolean +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>q : boolean + + if (b) { +>b : boolean + + d.r = 1 +>d.r = 1 : 1 +>d.r : number +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>r : number +>1 : 1 + } + else { + d.r = 2 +>d.r = 2 : 2 +>d.r : number +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>r : number +>2 : 2 + } + d.r +>d.r : number +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>r : number + + if (b) { +>b : boolean + + d.s = 'hi' +>d.s = 'hi' : "hi" +>d.s : string +>d : { (): void; e: number; q: boolean; r: number; s: string; } +>s : string +>'hi' : "hi" + } + return d +>d : { (): void; e: number; q: boolean; r: number; s: string; } +} +// OK to access possibly-unassigned properties outside the initialising scope +var test = f(true).s +>test : string +>f(true).s : string +>f(true) : { (): void; e: number; q: boolean; r: number; s: string; } +>f : (b: boolean) => { (): void; e: number; q: boolean; r: number; s: string; } +>true : true +>s : string + +function d() { +>d : typeof d +} +d.e = 12 +>d.e = 12 : 12 +>d.e : number +>d : typeof d +>e : number +>12 : 12 + +d.e +>d.e : number +>d : typeof d +>e : number + +if (!!false) { +>!!false : false +>!false : true +>false : false + + d.q = false +>d.q = false : false +>d.q : boolean +>d : typeof d +>q : boolean +>false : false +} +d.q +>d.q : boolean +>d : typeof d +>q : boolean + +if (!!false) { +>!!false : false +>!false : true +>false : false + + d.q = false +>d.q = false : false +>d.q : boolean +>d : typeof d +>q : boolean +>false : false +} +else { + d.q = true +>d.q = true : true +>d.q : boolean +>d : typeof d +>q : boolean +>true : true +} +d.q +>d.q : boolean +>d : typeof d +>q : boolean + +if (!!false) { +>!!false : false +>!false : true +>false : false + + d.r = 1 +>d.r = 1 : 1 +>d.r : number +>d : typeof d +>r : number +>1 : 1 +} +else { + d.r = 2 +>d.r = 2 : 2 +>d.r : number +>d : typeof d +>r : number +>2 : 2 +} +d.r +>d.r : number +>d : typeof d +>r : number + +// test function expressions too +const g = function() { +>g : { (): void; expando: number; both: string | number; } +>function() {} : { (): void; expando: number; both: string | number; } +} +if (!!false) { +>!!false : false +>!false : true +>false : false + + g.expando = 1 +>g.expando = 1 : 1 +>g.expando : number +>g : { (): void; expando: number; both: string | number; } +>expando : number +>1 : 1 +} +g.expando // error +>g.expando : number +>g : { (): void; expando: number; both: string | number; } +>expando : number + +if (!!false) { +>!!false : false +>!false : true +>false : false + + g.both = 'hi' +>g.both = 'hi' : "hi" +>g.both : string | number +>g : { (): void; expando: number; both: string | number; } +>both : string | number +>'hi' : "hi" +} +else { + g.both = 0 +>g.both = 0 : 0 +>g.both : string | number +>g : { (): void; expando: number; both: string | number; } +>both : string | number +>0 : 0 +} +g.both +>g.both : string | number +>g : { (): void; expando: number; both: string | number; } +>both : string | number + diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts new file mode 100644 index 00000000000..ee1038f48ca --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment36.ts @@ -0,0 +1,73 @@ +// @strict: true +function f(b: boolean) { + function d() { + } + d.e = 12 + d.e + + if (b) { + d.q = false + } + // error d.q might not be assigned + d.q + if (b) { + d.q = false + } + else { + d.q = true + } + d.q + if (b) { + d.r = 1 + } + else { + d.r = 2 + } + d.r + if (b) { + d.s = 'hi' + } + return d +} +// OK to access possibly-unassigned properties outside the initialising scope +var test = f(true).s + +function d() { +} +d.e = 12 +d.e + +if (!!false) { + d.q = false +} +d.q +if (!!false) { + d.q = false +} +else { + d.q = true +} +d.q +if (!!false) { + d.r = 1 +} +else { + d.r = 2 +} +d.r + +// test function expressions too +const g = function() { +} +if (!!false) { + g.expando = 1 +} +g.expando // error + +if (!!false) { + g.both = 'hi' +} +else { + g.both = 0 +} +g.both From eb06af19013e0265895d446b0b9f177dcf3541fa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 17 Sep 2018 13:01:53 -0700 Subject: [PATCH 21/47] Add tests --- .../controlFlow/controlFlowTruthiness.ts | 27 +++++++++++++++++++ .../keyof/keyofAndIndexedAccessErrors.ts | 6 +++++ 2 files changed, 33 insertions(+) diff --git a/tests/cases/conformance/controlFlow/controlFlowTruthiness.ts b/tests/cases/conformance/controlFlow/controlFlowTruthiness.ts index ba1947da13b..0245f9bfea0 100644 --- a/tests/cases/conformance/controlFlow/controlFlowTruthiness.ts +++ b/tests/cases/conformance/controlFlow/controlFlowTruthiness.ts @@ -68,3 +68,30 @@ function f6() { y; // string | undefined } } + +function f7(x: {}) { + if (x) { + x; // {} + } + else { + x; // {} + } +} + +function f8(x: T) { + if (x) { + x; // {} + } + else { + x; // {} + } +} + +function f9(x: T) { + if (x) { + x; // {} + } + else { + x; // never + } +} \ No newline at end of file diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts index bb2b9d95117..3660ff418e8 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts @@ -116,3 +116,9 @@ function f3, U extends T, J extends K>( tk = uj; uj = tk; // error } + +// The constraint of 'keyof T' is 'keyof T' +function f4(k: keyof T) { + k = 42; // error + k = "hello"; // error +} From 17080eb58f27a75cc2bb8e21308b7990d3751849 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 17 Sep 2018 13:02:01 -0700 Subject: [PATCH 22/47] Accept new baselines --- .../reference/controlFlowTruthiness.js | 52 ++++++++++++++++++- .../reference/controlFlowTruthiness.symbols | 51 ++++++++++++++++++ .../reference/controlFlowTruthiness.types | 47 +++++++++++++++++ .../keyofAndIndexedAccessErrors.errors.txt | 14 ++++- .../reference/keyofAndIndexedAccessErrors.js | 11 ++++ .../keyofAndIndexedAccessErrors.symbols | 16 ++++++ .../keyofAndIndexedAccessErrors.types | 16 ++++++ 7 files changed, 205 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/controlFlowTruthiness.js b/tests/baselines/reference/controlFlowTruthiness.js index b57befbd641..a841619ace5 100644 --- a/tests/baselines/reference/controlFlowTruthiness.js +++ b/tests/baselines/reference/controlFlowTruthiness.js @@ -67,7 +67,33 @@ function f6() { y; // string | undefined } } - + +function f7(x: {}) { + if (x) { + x; // {} + } + else { + x; // {} + } +} + +function f8(x: T) { + if (x) { + x; // {} + } + else { + x; // {} + } +} + +function f9(x: T) { + if (x) { + x; // {} + } + else { + x; // never + } +} //// [controlFlowTruthiness.js] function f1() { @@ -131,3 +157,27 @@ function f6() { y; // string | undefined } } +function f7(x) { + if (x) { + x; // {} + } + else { + x; // {} + } +} +function f8(x) { + if (x) { + x; // {} + } + else { + x; // {} + } +} +function f9(x) { + if (x) { + x; // {} + } + else { + x; // never + } +} diff --git a/tests/baselines/reference/controlFlowTruthiness.symbols b/tests/baselines/reference/controlFlowTruthiness.symbols index 72dd304f810..098a81e5164 100644 --- a/tests/baselines/reference/controlFlowTruthiness.symbols +++ b/tests/baselines/reference/controlFlowTruthiness.symbols @@ -140,3 +140,54 @@ function f6() { } } +function f7(x: {}) { +>f7 : Symbol(f7, Decl(controlFlowTruthiness.ts, 67, 1)) +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 69, 12)) + + if (x) { +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 69, 12)) + + x; // {} +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 69, 12)) + } + else { + x; // {} +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 69, 12)) + } +} + +function f8(x: T) { +>f8 : Symbol(f8, Decl(controlFlowTruthiness.ts, 76, 1)) +>T : Symbol(T, Decl(controlFlowTruthiness.ts, 78, 12)) +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 78, 15)) +>T : Symbol(T, Decl(controlFlowTruthiness.ts, 78, 12)) + + if (x) { +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 78, 15)) + + x; // {} +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 78, 15)) + } + else { + x; // {} +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 78, 15)) + } +} + +function f9(x: T) { +>f9 : Symbol(f9, Decl(controlFlowTruthiness.ts, 85, 1)) +>T : Symbol(T, Decl(controlFlowTruthiness.ts, 87, 12)) +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 87, 30)) +>T : Symbol(T, Decl(controlFlowTruthiness.ts, 87, 12)) + + if (x) { +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 87, 30)) + + x; // {} +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 87, 30)) + } + else { + x; // never +>x : Symbol(x, Decl(controlFlowTruthiness.ts, 87, 30)) + } +} diff --git a/tests/baselines/reference/controlFlowTruthiness.types b/tests/baselines/reference/controlFlowTruthiness.types index 225f6d0e7e2..454d094f406 100644 --- a/tests/baselines/reference/controlFlowTruthiness.types +++ b/tests/baselines/reference/controlFlowTruthiness.types @@ -157,3 +157,50 @@ function f6() { } } +function f7(x: {}) { +>f7 : (x: {}) => void +>x : {} + + if (x) { +>x : {} + + x; // {} +>x : {} + } + else { + x; // {} +>x : {} + } +} + +function f8(x: T) { +>f8 : (x: T) => void +>x : T + + if (x) { +>x : T + + x; // {} +>x : T + } + else { + x; // {} +>x : T + } +} + +function f9(x: T) { +>f9 : (x: T) => void +>x : T + + if (x) { +>x : T + + x; // {} +>x : T + } + else { + x; // never +>x : never + } +} diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt b/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt index dd5cbe050a9..4053189aea3 100644 --- a/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt @@ -61,9 +61,11 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(114,5): error Type 'string' is not assignable to type 'J'. tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(117,5): error TS2322: Type 'T[K]' is not assignable to type 'U[J]'. Type 'T' is not assignable to type 'U'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(122,5): error TS2322: Type '42' is not assignable to type 'keyof T'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(123,5): error TS2322: Type '"hello"' is not assignable to type 'keyof T'. -==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (36 errors) ==== +==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (38 errors) ==== class Shape { name: string; width: number; @@ -281,4 +283,14 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(117,5): error !!! error TS2322: Type 'T[K]' is not assignable to type 'U[J]'. !!! error TS2322: Type 'T' is not assignable to type 'U'. } + + // The constraint of 'keyof T' is 'keyof T' + function f4(k: keyof T) { + k = 42; // error + ~ +!!! error TS2322: Type '42' is not assignable to type 'keyof T'. + k = "hello"; // error + ~ +!!! error TS2322: Type '"hello"' is not assignable to type 'keyof T'. + } \ No newline at end of file diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.js b/tests/baselines/reference/keyofAndIndexedAccessErrors.js index c64f4df5331..a3124ce4c71 100644 --- a/tests/baselines/reference/keyofAndIndexedAccessErrors.js +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.js @@ -117,6 +117,12 @@ function f3, U extends T, J extends K>( tk = uj; uj = tk; // error } + +// The constraint of 'keyof T' is 'keyof T' +function f4(k: keyof T) { + k = 42; // error + k = "hello"; // error +} //// [keyofAndIndexedAccessErrors.js] @@ -178,3 +184,8 @@ function f3(t, k, tk, u, j, uk, tj, uj) { tk = uj; uj = tk; // error } +// The constraint of 'keyof T' is 'keyof T' +function f4(k) { + k = 42; // error + k = "hello"; // error +} diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.symbols b/tests/baselines/reference/keyofAndIndexedAccessErrors.symbols index f5c5f41dddf..72739eb76d7 100644 --- a/tests/baselines/reference/keyofAndIndexedAccessErrors.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.symbols @@ -412,3 +412,19 @@ function f3, U extends T, J extends K>( >tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) } +// The constraint of 'keyof T' is 'keyof T' +function f4(k: keyof T) { +>f4 : Symbol(f4, Decl(keyofAndIndexedAccessErrors.ts, 117, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 120, 12)) +>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 120, 25)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 120, 12)) +>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 120, 50)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 120, 12)) + + k = 42; // error +>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 120, 50)) + + k = "hello"; // error +>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 120, 50)) +} + diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.types b/tests/baselines/reference/keyofAndIndexedAccessErrors.types index c15f5ebb6ef..e5f8b6ee8e3 100644 --- a/tests/baselines/reference/keyofAndIndexedAccessErrors.types +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.types @@ -396,3 +396,19 @@ function f3, U extends T, J extends K>( >tk : T[K] } +// The constraint of 'keyof T' is 'keyof T' +function f4(k: keyof T) { +>f4 : (k: keyof T) => void +>k : keyof T + + k = 42; // error +>k = 42 : 42 +>k : keyof T +>42 : 42 + + k = "hello"; // error +>k = "hello" : "hello" +>k : keyof T +>"hello" : "hello" +} + From c9f190283ed2f671c519e0e8af410bee6958c472 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 17 Sep 2018 13:07:05 -0700 Subject: [PATCH 23/47] Fix non-toplevel prototype assignment (#27096) * Fix non-toplevel prototype assignment binder was using the wrong node to lookup the containing class type for prototype assignment, so it incorrectly put the prototype declaration on the class' symbol. This correction to the binder in turn required a change in getJSClassType in the checker. It now has to look at the "prototype" property for the prototype instead of looking on the class symbol's exports (which makes no sense). * Refactor per PR suggestion --- src/compiler/binder.ts | 4 +- src/compiler/checker.ts | 11 +- .../typeFromPrototypeAssignment2.errors.txt | 47 ++++++ .../typeFromPrototypeAssignment2.symbols | 127 ++++++++++++++ .../typeFromPrototypeAssignment2.types | 156 ++++++++++++++++++ .../salsa/typeFromPrototypeAssignment2.ts | 46 ++++++ 6 files changed, 382 insertions(+), 9 deletions(-) create mode 100644 tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt create mode 100644 tests/baselines/reference/typeFromPrototypeAssignment2.symbols create mode 100644 tests/baselines/reference/typeFromPrototypeAssignment2.types create mode 100644 tests/cases/conformance/salsa/typeFromPrototypeAssignment2.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index af3cf3b022d..38d6f558242 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2465,7 +2465,7 @@ namespace ts { node.left.parent = node; node.right.parent = node; const lhs = node.left as PropertyAccessEntityNameExpression; - bindPropertyAssignment(lhs, lhs, /*isPrototypeProperty*/ false); + bindPropertyAssignment(lhs.expression, lhs, /*isPrototypeProperty*/ false); } /** @@ -2522,7 +2522,7 @@ namespace ts { const isToplevel = isBinaryExpression(propertyAccess.parent) ? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === SyntaxKind.SourceFile : propertyAccess.parent.parent.kind === SyntaxKind.SourceFile; - if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace)) && isToplevel) { + if (isToplevel && !isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace))) { // make symbols or add declarations for intermediate containers const flags = SymbolFlags.Module | SymbolFlags.Assignment; const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2eae269b1a3..78628da2749 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20203,18 +20203,15 @@ namespace ts { assigned || inferred; } - function getAssignedClassType(symbol: Symbol) { + function getAssignedClassType(symbol: Symbol): Type | undefined { const decl = symbol.valueDeclaration; const assignmentSymbol = decl && decl.parent && (isFunctionDeclaration(decl) && getSymbolOfNode(decl) || isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) || isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent)); - if (assignmentSymbol) { - const prototype = forEach(assignmentSymbol.declarations, getAssignedJSPrototype); - if (prototype) { - return checkExpression(prototype); - } - } + const prototype = assignmentSymbol && assignmentSymbol.exports && assignmentSymbol.exports.get("prototype" as __String); + const init = prototype && getAssignedJSPrototype(prototype.valueDeclaration); + return init ? checkExpression(init) : undefined; } function getAssignedJSPrototype(node: Node) { diff --git a/tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt b/tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt new file mode 100644 index 00000000000..d4f66132d44 --- /dev/null +++ b/tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt @@ -0,0 +1,47 @@ +tests/cases/conformance/salsa/a.js(28,24): error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'. + + +==== tests/cases/conformance/salsa/a.js (1 errors) ==== + // non top-level: + // all references to _map, set, get, addon should be ok + (function container() { + /** @constructor */ + var Multimap = function() { + this._map = {}; + this._map + this.set + this.get + this.addon + }; + + Multimap.prototype = { + set: function() { + this._map + this.set + this.get + this.addon + }, + get() { + this._map + this.set + this.get + this.addon + } + } + + Multimap.prototype.addon = function () { + ~~~~~ +!!! error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'. + this._map + this.set + this.get + this.addon + } + + var mm = new Multimap(); + mm._map + mm.set + mm.get + mm.addon + }); + \ No newline at end of file diff --git a/tests/baselines/reference/typeFromPrototypeAssignment2.symbols b/tests/baselines/reference/typeFromPrototypeAssignment2.symbols new file mode 100644 index 00000000000..25ae9e31c69 --- /dev/null +++ b/tests/baselines/reference/typeFromPrototypeAssignment2.symbols @@ -0,0 +1,127 @@ +=== tests/cases/conformance/salsa/a.js === +// non top-level: +// all references to _map, set, get, addon should be ok +(function container() { +>container : Symbol(container, Decl(a.js, 2, 1)) + + /** @constructor */ + var Multimap = function() { +>Multimap : Symbol(Multimap, Decl(a.js, 4, 7)) + + this._map = {}; +>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31)) +>_map : Symbol(Multimap._map, Decl(a.js, 4, 31)) + + this._map +>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31)) +>_map : Symbol(Multimap._map, Decl(a.js, 4, 31)) + + this.set +>this.set : Symbol(set, Decl(a.js, 12, 26)) +>set : Symbol(set, Decl(a.js, 12, 26)) + + this.get +>this.get : Symbol(get, Decl(a.js, 18, 10)) +>get : Symbol(get, Decl(a.js, 18, 10)) + + this.addon +>this.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) +>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) + + }; + + Multimap.prototype = { +>Multimap.prototype : Symbol(Multimap.prototype, Decl(a.js, 10, 6)) +>Multimap : Symbol(Multimap, Decl(a.js, 4, 7)) +>prototype : Symbol(Multimap.prototype, Decl(a.js, 10, 6)) + + set: function() { +>set : Symbol(set, Decl(a.js, 12, 26)) + + this._map +>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31)) +>_map : Symbol(Multimap._map, Decl(a.js, 4, 31)) + + this.set +>this.set : Symbol(set, Decl(a.js, 12, 26)) +>set : Symbol(set, Decl(a.js, 12, 26)) + + this.get +>this.get : Symbol(get, Decl(a.js, 18, 10)) +>get : Symbol(get, Decl(a.js, 18, 10)) + + this.addon +>this.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) +>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) + + }, + get() { +>get : Symbol(get, Decl(a.js, 18, 10)) + + this._map +>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31)) +>_map : Symbol(Multimap._map, Decl(a.js, 4, 31)) + + this.set +>this.set : Symbol(set, Decl(a.js, 12, 26)) +>set : Symbol(set, Decl(a.js, 12, 26)) + + this.get +>this.get : Symbol(get, Decl(a.js, 18, 10)) +>get : Symbol(get, Decl(a.js, 18, 10)) + + this.addon +>this.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) +>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) + } + } + + Multimap.prototype.addon = function () { +>Multimap.prototype : Symbol(Multimap.addon, Decl(a.js, 25, 5)) +>Multimap : Symbol(Multimap, Decl(a.js, 4, 7)) +>prototype : Symbol(Multimap.prototype, Decl(a.js, 10, 6)) +>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) + + this._map +>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31)) +>_map : Symbol(Multimap._map, Decl(a.js, 4, 31)) + + this.set +>this.set : Symbol(set, Decl(a.js, 12, 26)) +>set : Symbol(set, Decl(a.js, 12, 26)) + + this.get +>this.get : Symbol(get, Decl(a.js, 18, 10)) +>get : Symbol(get, Decl(a.js, 18, 10)) + + this.addon +>this.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) +>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) + } + + var mm = new Multimap(); +>mm : Symbol(mm, Decl(a.js, 34, 7)) +>Multimap : Symbol(Multimap, Decl(a.js, 4, 7)) + + mm._map +>mm._map : Symbol(Multimap._map, Decl(a.js, 4, 31)) +>mm : Symbol(mm, Decl(a.js, 34, 7)) +>_map : Symbol(Multimap._map, Decl(a.js, 4, 31)) + + mm.set +>mm.set : Symbol(set, Decl(a.js, 12, 26)) +>mm : Symbol(mm, Decl(a.js, 34, 7)) +>set : Symbol(set, Decl(a.js, 12, 26)) + + mm.get +>mm.get : Symbol(get, Decl(a.js, 18, 10)) +>mm : Symbol(mm, Decl(a.js, 34, 7)) +>get : Symbol(get, Decl(a.js, 18, 10)) + + mm.addon +>mm.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) +>mm : Symbol(mm, Decl(a.js, 34, 7)) +>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5)) + +}); + diff --git a/tests/baselines/reference/typeFromPrototypeAssignment2.types b/tests/baselines/reference/typeFromPrototypeAssignment2.types new file mode 100644 index 00000000000..d37f421a356 --- /dev/null +++ b/tests/baselines/reference/typeFromPrototypeAssignment2.types @@ -0,0 +1,156 @@ +=== tests/cases/conformance/salsa/a.js === +// non top-level: +// all references to _map, set, get, addon should be ok +(function container() { +>(function container() { /** @constructor */ var Multimap = function() { this._map = {}; this._map this.set this.get this.addon }; Multimap.prototype = { set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon } } Multimap.prototype.addon = function () { this._map this.set this.get this.addon } var mm = new Multimap(); mm._map mm.set mm.get mm.addon}) : () => void +>function container() { /** @constructor */ var Multimap = function() { this._map = {}; this._map this.set this.get this.addon }; Multimap.prototype = { set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon } } Multimap.prototype.addon = function () { this._map this.set this.get this.addon } var mm = new Multimap(); mm._map mm.set mm.get mm.addon} : () => void +>container : () => void + + /** @constructor */ + var Multimap = function() { +>Multimap : typeof Multimap +>function() { this._map = {}; this._map this.set this.get this.addon } : typeof Multimap + + this._map = {}; +>this._map = {} : {} +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} +>{} : {} + + this._map +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} + + this.set +>this.set : () => void +>this : Multimap & { set: () => void; get(): void; } +>set : () => void + + this.get +>this.get : () => void +>this : Multimap & { set: () => void; get(): void; } +>get : () => void + + this.addon +>this.addon : () => void +>this : Multimap & { set: () => void; get(): void; } +>addon : () => void + + }; + + Multimap.prototype = { +>Multimap.prototype = { set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon } } : { set: () => void; get(): void; } +>Multimap.prototype : { set: () => void; get(): void; } +>Multimap : typeof Multimap +>prototype : { set: () => void; get(): void; } +>{ set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon } } : { set: () => void; get(): void; } + + set: function() { +>set : () => void +>function() { this._map this.set this.get this.addon } : () => void + + this._map +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} + + this.set +>this.set : () => void +>this : Multimap & { set: () => void; get(): void; } +>set : () => void + + this.get +>this.get : () => void +>this : Multimap & { set: () => void; get(): void; } +>get : () => void + + this.addon +>this.addon : () => void +>this : Multimap & { set: () => void; get(): void; } +>addon : () => void + + }, + get() { +>get : () => void + + this._map +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} + + this.set +>this.set : () => void +>this : Multimap & { set: () => void; get(): void; } +>set : () => void + + this.get +>this.get : () => void +>this : Multimap & { set: () => void; get(): void; } +>get : () => void + + this.addon +>this.addon : () => void +>this : Multimap & { set: () => void; get(): void; } +>addon : () => void + } + } + + Multimap.prototype.addon = function () { +>Multimap.prototype.addon = function () { this._map this.set this.get this.addon } : () => void +>Multimap.prototype.addon : any +>Multimap.prototype : { set: () => void; get(): void; } +>Multimap : typeof Multimap +>prototype : { set: () => void; get(): void; } +>addon : any +>function () { this._map this.set this.get this.addon } : () => void + + this._map +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} + + this.set +>this.set : () => void +>this : Multimap & { set: () => void; get(): void; } +>set : () => void + + this.get +>this.get : () => void +>this : Multimap & { set: () => void; get(): void; } +>get : () => void + + this.addon +>this.addon : () => void +>this : Multimap & { set: () => void; get(): void; } +>addon : () => void + } + + var mm = new Multimap(); +>mm : Multimap & { set: () => void; get(): void; } +>new Multimap() : Multimap & { set: () => void; get(): void; } +>Multimap : typeof Multimap + + mm._map +>mm._map : {} +>mm : Multimap & { set: () => void; get(): void; } +>_map : {} + + mm.set +>mm.set : () => void +>mm : Multimap & { set: () => void; get(): void; } +>set : () => void + + mm.get +>mm.get : () => void +>mm : Multimap & { set: () => void; get(): void; } +>get : () => void + + mm.addon +>mm.addon : () => void +>mm : Multimap & { set: () => void; get(): void; } +>addon : () => void + +}); + diff --git a/tests/cases/conformance/salsa/typeFromPrototypeAssignment2.ts b/tests/cases/conformance/salsa/typeFromPrototypeAssignment2.ts new file mode 100644 index 00000000000..68966c923d5 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPrototypeAssignment2.ts @@ -0,0 +1,46 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: a.js +// @strict: true + +// non top-level: +// all references to _map, set, get, addon should be ok +(function container() { + /** @constructor */ + var Multimap = function() { + this._map = {}; + this._map + this.set + this.get + this.addon + }; + + Multimap.prototype = { + set: function() { + this._map + this.set + this.get + this.addon + }, + get() { + this._map + this.set + this.get + this.addon + } + } + + Multimap.prototype.addon = function () { + this._map + this.set + this.get + this.addon + } + + var mm = new Multimap(); + mm._map + mm.set + mm.get + mm.addon +}); From bfc00935dfbfdcd34be3dfe52d3afe5f65bb0edb Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Sep 2018 14:14:55 -0700 Subject: [PATCH 24/47] Fix bug: Get mapped location of definition for findAllReferencesFull (#27113) --- src/server/session.ts | 28 +++++-- .../unittests/tsserverProjectSystem.ts | 80 ++++++++++++++++--- 2 files changed, 91 insertions(+), 17 deletions(-) diff --git a/src/server/session.ts b/src/server/session.ts index e6c4c33a53d..14ad20d7aae 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -336,16 +336,23 @@ namespace ts.server { function combineProjectOutputForReferences(projects: Projects, defaultProject: Project, initialLocation: sourcemaps.SourceMappableLocation, projectService: ProjectService): ReadonlyArray { const outputs: ReferencedSymbol[] = []; - combineProjectOutputWorker(projects, defaultProject, initialLocation, projectService, ({ project, location }, tryAddToTodo) => { + combineProjectOutputWorker(projects, defaultProject, initialLocation, projectService, ({ project, location }, getMappedLocation) => { for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.position) || emptyArray) { - let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, outputReferencedSymbol.definition)); + const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition)); + const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? outputReferencedSymbol.definition : { + ...outputReferencedSymbol.definition, + textSpan: createTextSpan(mappedDefinitionFile.position, outputReferencedSymbol.definition.textSpan.length), + fileName: mappedDefinitionFile.fileName, + }; + let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, definition)); if (!symbolToAddTo) { - symbolToAddTo = { definition: outputReferencedSymbol.definition, references: [] }; + symbolToAddTo = { definition, references: [] }; outputs.push(symbolToAddTo); } for (const ref of outputReferencedSymbol.references) { - if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(ref))) { + // If it's in a mapped file, that is added to the todo list by `getMappedLocation`. + if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !getMappedLocation(project, documentSpanLocation(ref))) { symbolToAddTo.references.push(ref); } } @@ -373,12 +380,17 @@ namespace ts.server { } } + type CombineProjectOutputCallback = ( + where: ProjectAndLocation, + getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => sourcemaps.SourceMappableLocation | undefined, + ) => void; + function combineProjectOutputWorker( projects: Projects, defaultProject: Project, initialLocation: TLocation, projectService: ProjectService, - cb: (where: ProjectAndLocation, getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => boolean) => void, + cb: CombineProjectOutputCallback, getDefinition: (() => sourcemaps.SourceMappableLocation | undefined) | undefined, ): void { let toDo: ProjectAndLocation[] | undefined; @@ -417,13 +429,13 @@ namespace ts.server { projectService: ProjectService, toDo: ProjectAndLocation[] | undefined, seenProjects: Map, - cb: (where: ProjectAndLocation, getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => boolean) => void, + cb: CombineProjectOutputCallback, ): ProjectAndLocation[] | undefined { if (projectAndLocation.project.getCancellationToken().isCancellationRequested()) return undefined; // Skip rest of toDo if cancelled cb(projectAndLocation, (project, location) => { seenProjects.set(projectAndLocation.project.projectName, true); const originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(project, location); - if (!originalLocation) return false; + if (!originalLocation) return undefined; const originalScriptInfo = projectService.getScriptInfo(originalLocation.fileName)!; toDo = toDo || []; @@ -437,7 +449,7 @@ namespace ts.server { for (const symlinkedProject of symlinkedProjects) addToTodo({ project: symlinkedProject, location: originalLocation as TLocation }, toDo!, seenProjects); }); } - return true; + return originalLocation; }); return toDo; } diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index b9ffc0c0153..40d79847baa 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -3491,7 +3491,7 @@ namespace ts.projectSystem { host.checkTimeoutQueueLength(2); // Update configured project and projects for open file checkProjectActualFiles(services.configuredProjects.get(config.path)!, filesWithFileA.map(f => f.path)); - // host.fileExists = originalFileExists; + // host.fileExists = originalFileExists; openFile(fileSubA); // This should create inferred project since fileSubA not on the disk checkProjectActualFiles(services.configuredProjects.get(config.path)!, mapDefined(filesWithFileA, f => f === fileA ? undefined : f.path)); @@ -3672,7 +3672,7 @@ namespace ts.projectSystem { path: `${projectRoot}/app1/tsconfig.json`, content: JSON.stringify({ files: ["app.ts", "../core/core.ts"], - compilerOptions: { outFile : "build/output.js" }, + compilerOptions: { outFile: "build/output.js" }, compileOnSave: true }) }; @@ -6778,9 +6778,9 @@ namespace ts.projectSystem { fileName: "/a.1.ts", textChanges: [ { - start: { line: 0, offset: 0 }, - end: { line: 0, offset: 0 }, - newText: "export const a = 0;", + start: { line: 0, offset: 0 }, + end: { line: 0, offset: 0 }, + newText: "export const a = 0;", }, ], } @@ -8672,7 +8672,7 @@ new C();` })); checkWatchedDirectories(host, [], /*recursive*/ false); checkWatchedDirectories(host, arrayFrom(expectedRecursiveDirectories.keys()), /*recursive*/ true); - } + } describe("from files in same folder", () => { function getFiles(fileContent: string) { @@ -9750,7 +9750,7 @@ declare class TestLib { function verifyATsConfigOriginalProject(session: TestSession) { checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1, configuredProjects: 1 }); verifyInferredProjectUnchanged(session); - verifyATsConfigProject(session); + verifyATsConfigProject(session); // Close user file should close all the projects closeFilesForSession([userTs], session); verifyOnlyOrphanInferredProject(session); @@ -9900,11 +9900,12 @@ declare class TestLib { verifyATsConfigWhenOpened(session); }); + interface ReferencesFullRequest extends protocol.FileLocationRequest { readonly command: protocol.CommandTypes.ReferencesFull; } + interface ReferencesFullResponse extends protocol.Response { readonly body: ReadonlyArray; } + it("findAllReferencesFull", () => { const session = makeSampleProjects(); - interface ReferencesFullRequest extends protocol.FileLocationRequest { command: protocol.CommandTypes.ReferencesFull; } - interface ReferencesFullResponse extends protocol.Response { body: ReadonlyArray; } const responseFull = executeSessionRequest(session, protocol.CommandTypes.ReferencesFull, protocolFileLocationFromSubstring(userTs, "fnA()")); function fnAVoid(kind: SymbolDisplayPartKind): SymbolDisplayPart[] { @@ -9961,6 +9962,67 @@ declare class TestLib { verifyATsConfigOriginalProject(session); }); + it("findAllReferencesFull definition is in mapped file", () => { + const aTs: File = { path: "/a/a.ts", content: `function f() {}` }; + const aTsconfig: File = { + path: "/a/tsconfig.json", + content: JSON.stringify({ compilerOptions: { declaration: true, declarationMap: true, outFile: "../bin/a.js" } }), + }; + const bTs: File = { path: "/b/b.ts", content: `f();` }; + const bTsconfig: File = { path: "/b/tsconfig.json", content: JSON.stringify({ references: [{ path: "../a" }] }) }; + const aDts: File = { path: "/bin/a.d.ts", content: `declare function f(): void;\n//# sourceMappingURL=a.d.ts.map` }; + const aDtsMap: File = { + path: "/bin/a.d.ts.map", + content: JSON.stringify({ version: 3, file: "a.d.ts", sourceRoot: "", sources: ["../a/a.ts"], names: [], mappings: "AAAA,iBAAS,CAAC,SAAK" }), + }; + + const session = createSession(createServerHost([aTs, aTsconfig, bTs, bTsconfig, aDts, aDtsMap])); + checkDeclarationFiles(aTs, session, [aDtsMap, aDts]); + openFilesForSession([bTs], session); + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 }); + + const responseFull = executeSessionRequest(session, protocol.CommandTypes.ReferencesFull, protocolFileLocationFromSubstring(bTs, "f()")); + + assert.deepEqual>(responseFull, [ + { + definition: { + containerKind: ScriptElementKind.unknown, + containerName: "", + displayParts: [ + keywordPart(SyntaxKind.FunctionKeyword), + spacePart(), + displayPart("f", SymbolDisplayPartKind.functionName), + punctuationPart(SyntaxKind.OpenParenToken), + punctuationPart(SyntaxKind.CloseParenToken), + punctuationPart(SyntaxKind.ColonToken), + spacePart(), + keywordPart(SyntaxKind.VoidKeyword), + ], + fileName: aTs.path, + kind: ScriptElementKind.functionElement, + name: "function f(): void", + textSpan: { start: 9, length: 1 }, + }, + references: [ + { + fileName: bTs.path, + isDefinition: false, + isInString: undefined, + isWriteAccess: false, + textSpan: { start: 0, length: 1 }, + }, + { + fileName: aTs.path, + isDefinition: true, + isInString: undefined, + isWriteAccess: true, + textSpan: { start: 9, length: 1 }, + }, + ], + } + ]); + }); + it("findAllReferences -- target does not exist", () => { const session = makeSampleProjects(); From cd5b9fa7dd65ac0f76d921cb968e44d5069fb553 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 17 Sep 2018 14:19:01 -0700 Subject: [PATCH 25/47] Update user baselines (#27141) --- tests/baselines/reference/user/async.log | 4 -- .../user/chrome-devtools-frontend.log | 65 +++++++++++-------- tests/baselines/reference/user/debug.log | 2 +- tests/baselines/reference/user/formik.log | 17 ----- .../baselines/reference/user/graceful-fs.log | 8 --- tests/baselines/reference/user/jimp.log | 6 +- tests/baselines/reference/user/lodash.log | 58 ++++++++--------- tests/baselines/reference/user/npm.log | 8 --- tests/baselines/reference/user/uglify-js.log | 2 +- 9 files changed, 71 insertions(+), 99 deletions(-) delete mode 100644 tests/baselines/reference/user/formik.log diff --git a/tests/baselines/reference/user/async.log b/tests/baselines/reference/user/async.log index 791445bfddc..32b54ba4a0e 100644 --- a/tests/baselines/reference/user/async.log +++ b/tests/baselines/reference/user/async.log @@ -92,8 +92,6 @@ node_modules/async/dist/async.js(31,29): error TS1003: Identifier expected. node_modules/async/dist/async.js(31,30): error TS1003: Identifier expected. node_modules/async/dist/async.js(257,56): error TS2339: Property 'Object' does not exist on type 'Window'. node_modules/async/dist/async.js(298,7): error TS2454: Variable 'unmasked' is used before being assigned. -node_modules/async/dist/async.js(480,35): error TS2538: Type 'true' cannot be used as an index type. -node_modules/async/dist/async.js(480,59): error TS2538: Type 'true' cannot be used as an index type. node_modules/async/dist/async.js(622,80): error TS2339: Property 'nodeType' does not exist on type 'NodeModule'. node_modules/async/dist/async.js(748,84): error TS2339: Property 'nodeType' does not exist on type 'NodeModule'. node_modules/async/dist/async.js(754,49): error TS2339: Property 'process' does not exist on type 'false | Global'. @@ -523,8 +521,6 @@ node_modules/async/internal/filter.js(64,29): error TS2695: Left side of comma o node_modules/async/internal/filter.js(66,18): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/internal/filter.js(72,19): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/internal/filter.js(73,27): error TS2695: Left side of comma operator is unused and has no side effects. -node_modules/async/internal/getIterator.js(8,35): error TS2538: Type 'true' cannot be used as an index type. -node_modules/async/internal/getIterator.js(8,59): error TS2538: Type 'true' cannot be used as an index type. node_modules/async/internal/initialParams.js(9,21): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/internal/iterator.js(41,18): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/internal/iterator.js(51,10): error TS2695: Left side of comma operator is unused and has no side effects. diff --git a/tests/baselines/reference/user/chrome-devtools-frontend.log b/tests/baselines/reference/user/chrome-devtools-frontend.log index cf555239405..7a53da21ec4 100644 --- a/tests/baselines/reference/user/chrome-devtools-frontend.log +++ b/tests/baselines/reference/user/chrome-devtools-frontend.log @@ -29,10 +29,8 @@ node_modules/chrome-devtools-frontend/front_end/Runtime.js(270,9): error TS2322: Type 'void' is not assignable to type 'undefined'. node_modules/chrome-devtools-frontend/front_end/Runtime.js(280,5): error TS2322: Type 'Promise' is not assignable to type 'Promise'. node_modules/chrome-devtools-frontend/front_end/Runtime.js(283,7): error TS2554: Expected 2-3 arguments, but got 1. -node_modules/chrome-devtools-frontend/front_end/Runtime.js(527,9): error TS2322: Type 'Function' is not assignable to type 'new () => any'. - Type 'Function' provides no match for the signature 'new (): any'. -node_modules/chrome-devtools-frontend/front_end/Runtime.js(527,49): error TS2352: Conversion of type 'Window' to type 'Function' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. - Property 'apply' is missing in type 'Window'. +node_modules/chrome-devtools-frontend/front_end/Runtime.js(527,49): error TS2352: Conversion of type 'Window' to type 'new () => any' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. + Type 'Window' provides no match for the signature 'new (): any'. node_modules/chrome-devtools-frontend/front_end/Runtime.js(539,20): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. node_modules/chrome-devtools-frontend/front_end/Runtime.js(693,7): error TS2322: Type 'Promise' is not assignable to type 'Promise'. Type 'boolean' is not assignable to type 'undefined'. @@ -142,7 +140,6 @@ node_modules/chrome-devtools-frontend/front_end/accessibility/AXBreadcrumbsPane. node_modules/chrome-devtools-frontend/front_end/accessibility/AXBreadcrumbsPane.js(274,42): error TS2554: Expected 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/accessibility/AXBreadcrumbsPane.js(298,19): error TS2339: Property 'breadcrumb' does not exist on type 'Element'. node_modules/chrome-devtools-frontend/front_end/accessibility/AXBreadcrumbsPane.js(302,23): error TS2339: Property 'tabIndex' does not exist on type 'Element'. -node_modules/chrome-devtools-frontend/front_end/accessibility/AXBreadcrumbsPane.js(314,15): error TS1110: Type expected. node_modules/chrome-devtools-frontend/front_end/accessibility/AXBreadcrumbsPane.js(323,23): error TS2339: Property 'style' does not exist on type 'Element'. node_modules/chrome-devtools-frontend/front_end/accessibility/AXBreadcrumbsPane.js(330,27): error TS2339: Property 'createChild' does not exist on type 'Element'. node_modules/chrome-devtools-frontend/front_end/accessibility/AXBreadcrumbsPane.js(391,50): error TS2345: Argument of type '0' is not assignable to parameter of type 'string'. @@ -284,7 +281,7 @@ node_modules/chrome-devtools-frontend/front_end/animation/AnimationModel.js(811, node_modules/chrome-devtools-frontend/front_end/animation/AnimationModel.js(811,44): error TS2300: Duplicate identifier 'Request'. node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(7,11): error TS2339: Property 'AnimationScreenshotPopover' does not exist on type '{ new (effect?: AnimationEffect, timeline?: AnimationTimeline): Animation; prototype: Animation; }'. node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(9,23): error TS2304: Cannot find name 'Image'. -node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(18,39): error TS2322: Type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to type 'Node'. +node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(18,39): error TS2345: Argument of type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to parameter of type 'Node'. Property 'baseURI' is missing in type 'new (width?: number, height?: number) => HTMLImageElement'. node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(19,13): error TS2339: Property 'style' does not exist on type 'new (width?: number, height?: number) => HTMLImageElement'. node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(22,21): error TS2339: Property 'style' does not exist on type 'new (width?: number, height?: number) => HTMLImageElement'. @@ -1289,8 +1286,19 @@ node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighth node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44348,15): error TS2339: Property 'keysArray' does not exist on type 'Map'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44356,15): error TS2339: Property 'inverse' does not exist on type 'Map'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44361,8): error TS2339: Property 'set' does not exist on type 'Multimap'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44439,17): error TS2339: Property 'get' does not exist on type 'Multimap'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44458,18): error TS2339: Property 'keysArray' does not exist on type 'Map'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44467,15): error TS2339: Property 'keysArray' does not exist on type 'Multimap'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44469,8): error TS2339: Property 'pushAll' does not exist on type 'any[]'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44469,21): error TS2339: Property 'get' does not exist on type 'Multimap'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44495,27): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44525,22): error TS2339: Property '_outgoingCallback' does not exist on type 'CallbackBarrier'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44527,13): error TS2339: Property '_incomingCallback' does not exist on type 'CallbackBarrier'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44535,22): error TS2339: Property '_outgoingCallback' does not exist on type 'CallbackBarrier'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44536,6): error TS2339: Property '_outgoingCallback' does not exist on type 'CallbackBarrier'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44538,6): error TS2339: Property '_outgoingCallback' does not exist on type 'CallbackBarrier'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44568,50): error TS2339: Property '_outgoingCallback' does not exist on type 'CallbackBarrier'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44569,6): error TS2339: Property '_outgoingCallback' does not exist on type 'CallbackBarrier'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44584,6): error TS2339: Property 'setImmediate' does not exist on type 'Window'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44595,19): error TS2339: Property 'spread' does not exist on type 'Promise'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(44610,19): error TS2339: Property 'catchException' does not exist on type 'Promise'. @@ -3010,6 +3018,7 @@ node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighth node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(67117,1): error TS2322: Type 'string[]' is not assignable to type 'RegExpExecArray'. Property 'index' is missing in type 'string[]'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(67167,19): error TS2339: Property 'parse' does not exist on type 'Link'. +node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(67225,13): error TS2339: Property 'get' does not exist on type 'Link'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(67300,14): error TS2339: Property 'Channels' does not exist on type '{}'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(67300,35): error TS2339: Property 'Channels' does not exist on type '{}'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(67301,24): error TS2339: Property 'Channels' does not exist on type '{}'. @@ -3310,6 +3319,8 @@ node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(2858,32): error node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(2858,49): error TS2339: Property 'right' does not exist on type 'never'. node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(3034,25): error TS2339: Property 'xRel' does not exist on type 'Pos'. node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(4840,5): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(5583,12): error TS2339: Property 'collapse' does not exist on type 'BranchChunk'. +node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(5615,18): error TS2339: Property 'maybeSpill' does not exist on type 'BranchChunk'. node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(5675,35): error TS2339: Property 'line' does not exist on type 'LineWidget'. node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(5675,61): error TS2339: Property 'line' does not exist on type 'LineWidget'. node_modules/chrome-devtools-frontend/front_end/cm/codemirror.js(5693,57): error TS2339: Property 'line' does not exist on type 'LineWidget'. @@ -3419,6 +3430,7 @@ node_modules/chrome-devtools-frontend/front_end/cm/overlay.js(16,19): error TS23 node_modules/chrome-devtools-frontend/front_end/cm/overlay.js(16,43): error TS2304: Cannot find name 'define'. node_modules/chrome-devtools-frontend/front_end/cm/overlay.js(17,5): error TS2304: Cannot find name 'define'. node_modules/chrome-devtools-frontend/front_end/cm_headless/headlesscodemirror.js(30,14): error TS2403: Subsequent variable declarations must have the same type. Variable 'ok' must be of type 'boolean', but here has type 'any'. +node_modules/chrome-devtools-frontend/front_end/cm_headless/headlesscodemirror.js(35,17): error TS2339: Property 'eat' does not exist on type 'StringStream'. node_modules/chrome-devtools-frontend/front_end/cm_headless/headlesscodemirror.js(74,1): error TS2719: Type 'typeof StringStream' is not assignable to type 'typeof StringStream'. Two different types with this name exist, but they are unrelated. Type 'StringStream' is not assignable to type 'StringStream & { backUp: (n: any) => void; column: () => void; current: () => void; eat: (match: any) => void; eatSpace: () => void; eatWhile: (match: any) => void; eol: () => void; indentation: () => void; ... 5 more ...; sol: () => void; }'. Type 'StringStream' is not assignable to type '{ backUp: (n: any) => void; column: () => void; current: () => void; eat: (match: any) => void; eatSpace: () => void; eatWhile: (match: any) => void; eol: () => void; indentation: () => void; match: (pattern: string | RegExp, consume?: boolean, caseInsensitive?: boolean) => void; ... 4 more ...; sol: () => void; }'. @@ -4400,7 +4412,6 @@ node_modules/chrome-devtools-frontend/front_end/coverage/CoverageDecorationManag node_modules/chrome-devtools-frontend/front_end/coverage/CoverageDecorationManager.js(247,24): error TS2694: Namespace 'Coverage' has no exported member 'RawLocation'. node_modules/chrome-devtools-frontend/front_end/coverage/CoverageDecorationManager.js(248,24): error TS2694: Namespace 'Coverage' has no exported member 'RawLocation'. node_modules/chrome-devtools-frontend/front_end/coverage/CoverageDecorationManager.js(255,22): error TS2694: Namespace 'Common' has no exported member 'Event'. -node_modules/chrome-devtools-frontend/front_end/coverage/CoverageDecorationManager.js(258,34): error TS1110: Type expected. node_modules/chrome-devtools-frontend/front_end/coverage/CoverageDecorationManager.js(277,18): error TS2339: Property 'uninstallGutter' does not exist on type 'CodeMirrorTextEditor'. node_modules/chrome-devtools-frontend/front_end/coverage/CoverageDecorationManager.js(293,16): error TS2339: Property 'uninstallGutter' does not exist on type 'CodeMirrorTextEditor'. node_modules/chrome-devtools-frontend/front_end/coverage/CoverageDecorationManager.js(294,16): error TS2339: Property 'installGutter' does not exist on type 'CodeMirrorTextEditor'. @@ -4465,7 +4476,6 @@ node_modules/chrome-devtools-frontend/front_end/coverage/CoverageView.js(57,54): node_modules/chrome-devtools-frontend/front_end/coverage/CoverageView.js(141,5): error TS2322: Type 'Timer' is not assignable to type 'number'. node_modules/chrome-devtools-frontend/front_end/coverage/CoverageView.js(187,55): error TS2339: Property 'bytesToString' does not exist on type 'NumberConstructor'. node_modules/chrome-devtools-frontend/front_end/coverage/CoverageView.js(187,85): error TS2339: Property 'bytesToString' does not exist on type 'NumberConstructor'. -node_modules/chrome-devtools-frontend/front_end/coverage/CoverageView.js(231,59): error TS1110: Type expected. node_modules/chrome-devtools-frontend/front_end/coverage_test_runner/CoverageTestRunner.js(12,27): error TS2339: Property 'runtime' does not exist on type 'Window'. node_modules/chrome-devtools-frontend/front_end/coverage_test_runner/CoverageTestRunner.js(20,27): error TS2339: Property 'runtime' does not exist on type 'Window'. node_modules/chrome-devtools-frontend/front_end/coverage_test_runner/CoverageTestRunner.js(28,27): error TS2339: Property 'runtime' does not exist on type 'Window'. @@ -5867,6 +5877,8 @@ node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeToolbar.js(3 node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeToolbar.js(302,71): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeToolbar.js(303,9): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeToolbar.js(305,44): error TS2555: Expected at least 2 arguments, but got 1. +node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeToolbar.js(338,5): error TS2322: Type 'ToolbarItem' is not assignable to type '{ item(): any & any; } & { item(): any & any; }'. + Type 'ToolbarItem' is not assignable to type '{ item(): any & any; }'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeToolbar.js(338,5): error TS2322: Type 'ToolbarItem' is not assignable to type '{ item(): any & any; } & { item(): any & any; }'. Type 'ToolbarItem' is not assignable to type '{ item(): any & any; }'. Property 'item' is missing in type 'ToolbarItem'. @@ -5899,8 +5911,6 @@ node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(83,9 node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(84,7): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(84,34): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(84,63): error TS2555: Expected at least 2 arguments, but got 1. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(103,12): error TS2339: Property '_model' does not exist on type 'typeof DeviceModeView'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(104,12): error TS2339: Property '_model' does not exist on type 'typeof DeviceModeView'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(105,9): error TS2339: Property 'consume' does not exist on type 'Event'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(132,22): error TS2694: Namespace 'Common' has no exported member 'Event'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(143,22): error TS2694: Namespace 'Common' has no exported member 'Event'. @@ -5925,18 +5935,8 @@ node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(483, node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeView.js(500,22): error TS2339: Property 'createChild' does not exist on type 'Element'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(18,22): error TS2339: Property 'singleton' does not exist on type 'Window'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(33,24): error TS2694: Namespace 'Protocol' has no exported member 'Page'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(38,30): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(39,26): error TS2339: Property 'setNonEmulatedAvailableSize' does not exist on type 'typeof DeviceModeView'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(41,28): error TS2339: Property 'captureFullSizeScreenshot' does not exist on type 'typeof DeviceModeView'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(43,28): error TS2339: Property 'captureAreaScreenshot' does not exist on type 'typeof DeviceModeView'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(45,28): error TS2339: Property 'captureScreenshot' does not exist on type 'typeof DeviceModeView'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(50,22): error TS2694: Namespace 'Common' has no exported member 'Event'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(53,37): error TS2694: Namespace 'Protocol' has no exported member 'Page'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(63,66): error TS2339: Property 'isShowing' does not exist on type 'typeof DeviceModeView'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(70,32): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(71,28): error TS2339: Property 'show' does not exist on type 'typeof DeviceModeView'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(73,64): error TS2339: Property 'element' does not exist on type 'typeof DeviceModeView'. -node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(76,30): error TS2339: Property 'detach' does not exist on type 'typeof DeviceModeView'. node_modules/chrome-devtools-frontend/front_end/emulation/DeviceModeWrapper.js(120,45): error TS2694: Namespace 'Protocol' has no exported member 'Page'. node_modules/chrome-devtools-frontend/front_end/emulation/DevicesSettingsTab.js(15,31): error TS2339: Property 'createChild' does not exist on type 'Element'. node_modules/chrome-devtools-frontend/front_end/emulation/DevicesSettingsTab.js(16,46): error TS2555: Expected at least 2 arguments, but got 1. @@ -6096,8 +6096,10 @@ node_modules/chrome-devtools-frontend/front_end/event_listeners/EventListenersVi node_modules/chrome-devtools-frontend/front_end/event_listeners/EventListenersView.js(321,13): error TS2339: Property 'consume' does not exist on type 'Event'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(130,25): error TS2339: Property 'sendRequest' does not exist on type 'ExtensionServerClient'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(132,23): error TS2339: Property 'registerHandler' does not exist on type 'ExtensionServerClient'. +node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(132,68): error TS2339: Property '_dispatch' does not exist on type 'EventSinkImpl'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(145,25): error TS2339: Property 'sendRequest' does not exist on type 'ExtensionServerClient'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(149,19): error TS1110: Type expected. +node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(161,14): error TS2339: Property '_fire' does not exist on type 'EventSinkImpl'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(186,12): error TS2339: Property '_fire' does not exist on type 'EventSinkImpl'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(203,23): error TS2339: Property 'sendRequest' does not exist on type 'ExtensionServerClient'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(207,23): error TS2339: Property 'sendRequest' does not exist on type 'ExtensionServerClient'. @@ -6120,7 +6122,9 @@ node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(371,1 node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(381,12): error TS8022: JSDoc '@extends' is not attached to a class. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(391,12): error TS8022: JSDoc '@extends' is not attached to a class. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(401,44): error TS2339: Property 'nextObjectId' does not exist on type 'ExtensionServerClient'. +node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(404,21): error TS2339: Property '_id' does not exist on type 'ExtensionPanelImpl'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(410,23): error TS2339: Property 'sendRequest' does not exist on type 'ExtensionServerClient'. +node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(418,60): error TS2339: Property '_id' does not exist on type 'ExtensionPanelImpl'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(419,23): error TS2339: Property 'sendRequest' does not exist on type 'ExtensionServerClient'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(429,12): error TS8022: JSDoc '@extends' is not attached to a class. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(435,23): error TS2339: Property 'sendRequest' does not exist on type 'ExtensionServerClient'. @@ -6143,6 +6147,7 @@ node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(662,2 node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(678,10): error TS2339: Property 'registerHandler' does not exist on type 'ExtensionServerClient'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(678,43): error TS2551: Property '_onCallback' does not exist on type 'ExtensionServerClient'. Did you mean '_callbacks'? node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(682,49): error TS2339: Property '_onMessage' does not exist on type 'ExtensionServerClient'. +node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(695,34): error TS2339: Property '_registerCallback' does not exist on type 'ExtensionServerClient'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(789,21): error TS2339: Property 'exposeWebInspectorNamespace' does not exist on type 'ExtensionDescriptor'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionAPI.js(790,12): error TS2339: Property 'webInspector' does not exist on type 'Window'. node_modules/chrome-devtools-frontend/front_end/extensions/ExtensionPanel.js(232,23): error TS2339: Property 'style' does not exist on type 'Element'. @@ -6318,14 +6323,11 @@ node_modules/chrome-devtools-frontend/front_end/formatter_worker/ESTreeWalker.js Property 'start' is missing in type 'TemplateLiteralNode'. node_modules/chrome-devtools-frontend/front_end/formatter_worker/ESTreeWalker.js(63,57): error TS2345: Argument of type 'TemplateLiteralNode' is not assignable to parameter of type 'Node'. node_modules/chrome-devtools-frontend/front_end/formatter_worker/ESTreeWalker.js(65,66): error TS2345: Argument of type 'TemplateLiteralNode' is not assignable to parameter of type 'Node'. -node_modules/chrome-devtools-frontend/front_end/formatter_worker/ESTreeWalker.js(89,53): error TS2300: Duplicate identifier 'SkipSubtree'. -node_modules/chrome-devtools-frontend/front_end/formatter_worker/ESTreeWalker.js(90,30): error TS2300: Duplicate identifier 'SkipSubtree'. node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormattedContentBuilder.js(47,39): error TS2339: Property 'peekLast' does not exist on type 'any[]'. node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormatterWorker.js(43,13): error TS1345: An expression of type 'void' cannot be tested for truthiness node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormatterWorker.js(44,24): error TS2339: Property 'token' does not exist on type 'void'. node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormatterWorker.js(46,20): error TS2345: Argument of type 'void' is not assignable to parameter of type 'string'. node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormatterWorker.js(46,69): error TS2339: Property 'length' does not exist on type 'void'. -node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormatterWorker.js(58,26): error TS1110: Type expected. node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormatterWorker.js(96,3): error TS2554: Expected 2-3 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormatterWorker.js(103,45): error TS2322: Type 'number' is not assignable to type 'boolean'. node_modules/chrome-devtools-frontend/front_end/formatter_worker/FormatterWorker.js(138,3): error TS2554: Expected 2-3 arguments, but got 1. @@ -8000,12 +8002,14 @@ node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(694,31): e node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(701,13): error TS2403: Subsequent variable declarations must have the same type. Variable 'entryIndex' must be of type 'any', but here has type 'number'. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(796,43): error TS2339: Property 'peekLast' does not exist on type 'any[]'. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(903,60): error TS2694: Namespace 'PerfUI.FlameChart' has no exported member 'Group'. -node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(907,17): error TS1110: Type expected. +node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(915,27): error TS2339: Property 'peekLast' does not exist on type '{ nestingLevel: number; visible: boolean; }[]'. +node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(919,45): error TS2339: Property 'peekLast' does not exist on type '{ nestingLevel: number; visible: boolean; }[]'. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(931,33): error TS2694: Namespace 'PerfUI.FlameChart' has no exported member 'Group'. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(940,33): error TS2694: Namespace 'PerfUI.FlameChart' has no exported member 'Group'. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(1027,38): error TS2339: Property 'lowerBound' does not exist on type 'any[]'. -node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(1167,15): error TS1110: Type expected. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(1169,70): error TS2339: Property 'peekLast' does not exist on type 'any[]'. +node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(1176,27): error TS2339: Property 'peekLast' does not exist on type '{ nestingLevel: number; visible: boolean; }[]'. +node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(1182,43): error TS2339: Property 'peekLast' does not exist on type '{ nestingLevel: number; visible: boolean; }[]'. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(1273,25): error TS2339: Property 'style' does not exist on type 'Element'. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(1286,19): error TS2339: Property 'constrain' does not exist on type 'NumberConstructor'. node_modules/chrome-devtools-frontend/front_end/perf_ui/FlameChart.js(1390,34): error TS2694: Namespace 'PerfUI.FlameChart' has no exported member 'GroupStyle'. @@ -8322,6 +8326,11 @@ node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1164,15): node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1169,24): error TS2304: Cannot find name 'KEY'. node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1169,30): error TS2304: Cannot find name 'VALUE'. node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1171,15): error TS2339: Property 'inverse' does not exist on type 'Map'. +node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1200,13): error TS2345: Argument of type 'V' is not assignable to parameter of type 'V'. +node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1211,5): error TS2719: Type 'Set' is not assignable to type 'Set'. Two different types with this name exist, but they are unrelated. + Type 'V' is not assignable to type 'V'. Two different types with this name exist, but they are unrelated. +node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1231,20): error TS2345: Argument of type 'V' is not assignable to parameter of type 'V'. +node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1267,22): error TS2339: Property 'keysArray' does not exist on type 'Map>'. node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1277,14): error TS2339: Property 'pushAll' does not exist on type 'any[]'. node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1277,40): error TS2339: Property 'valuesArray' does not exist on type 'Set'. node_modules/chrome-devtools-frontend/front_end/platform/utilities.js(1299,35): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. @@ -12007,7 +12016,7 @@ node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataP node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(621,36): error TS2339: Property 'preciseMillisToString' does not exist on type 'NumberConstructor'. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(654,37): error TS2339: Property 'naturalHeight' does not exist on type 'new (width?: number, height?: number) => HTMLImageElement'. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(655,39): error TS2339: Property 'naturalWidth' does not exist on type 'new (width?: number, height?: number) => HTMLImageElement'. -node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(660,23): error TS2322: Type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to type 'CanvasImageSource'. +node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(660,23): error TS2345: Argument of type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to parameter of type 'CanvasImageSource'. Type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to type 'ImageBitmap'. Property 'height' is missing in type 'new (width?: number, height?: number) => HTMLImageElement'. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(788,33): error TS2694: Namespace 'PerfUI.FlameChart' has no exported member 'GroupStyle'. @@ -12519,7 +12528,7 @@ node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1649 node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1651,33): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1652,33): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1652,69): error TS2339: Property 'millisToString' does not exist on type 'NumberConstructor'. -node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1657,64): error TS2322: Type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to type 'Node'. +node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1657,64): error TS2345: Argument of type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to parameter of type 'Node'. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1664,11): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1665,67): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1675,5): error TS2322: Type 'DocumentFragment' is not assignable to type 'Element'. @@ -12654,7 +12663,6 @@ node_modules/chrome-devtools-frontend/front_end/timeline_model/TimelineModel.js( node_modules/chrome-devtools-frontend/front_end/timeline_model/TimelineModel.js(1780,33): error TS2694: Namespace 'Protocol' has no exported member 'Runtime'. node_modules/chrome-devtools-frontend/front_end/timeline_model/TimelineModel.js(1811,25): error TS2694: Namespace 'Protocol' has no exported member 'Runtime'. node_modules/chrome-devtools-frontend/front_end/timeline_model/TimelineModel.js(1819,32): error TS2694: Namespace 'Protocol' has no exported member 'Runtime'. -node_modules/chrome-devtools-frontend/front_end/timeline_model/TimelineModelFilter.js(43,22): error TS1110: Type expected. node_modules/chrome-devtools-frontend/front_end/timeline_model/TimelineProfileTree.js(74,26): error TS2502: 'parent' is referenced directly or indirectly in its own type annotation. node_modules/chrome-devtools-frontend/front_end/timeline_model/TimelineProfileTree.js(168,31): error TS2345: Argument of type 'string | symbol' is not assignable to parameter of type 'string'. Type 'symbol' is not assignable to type 'string'. @@ -12911,6 +12919,7 @@ node_modules/chrome-devtools-frontend/front_end/ui/KeyboardShortcut.js(97,36): e node_modules/chrome-devtools-frontend/front_end/ui/KeyboardShortcut.js(108,36): error TS2694: Namespace 'UI.KeyboardShortcut' has no exported member 'Descriptor'. node_modules/chrome-devtools-frontend/front_end/ui/KeyboardShortcut.js(135,42): error TS2694: Namespace 'UI.KeyboardShortcut' has no exported member 'Key'. node_modules/chrome-devtools-frontend/front_end/ui/KeyboardShortcut.js(144,42): error TS2694: Namespace 'UI.KeyboardShortcut' has no exported member 'Key'. +node_modules/chrome-devtools-frontend/front_end/ui/KeyboardShortcut.js(197,9): error TS1127: Invalid character. node_modules/chrome-devtools-frontend/front_end/ui/KeyboardShortcut.js(216,21): error TS2551: Property 'Key' does not exist on type 'typeof KeyboardShortcut'. Did you mean 'Keys'? node_modules/chrome-devtools-frontend/front_end/ui/KeyboardShortcut.js(218,50): error TS2694: Namespace 'UI.KeyboardShortcut' has no exported member 'Key'. node_modules/chrome-devtools-frontend/front_end/ui/KeyboardShortcut.js(289,21): error TS2300: Duplicate identifier 'Descriptor'. diff --git a/tests/baselines/reference/user/debug.log b/tests/baselines/reference/user/debug.log index df15979cdb2..dba95024e7c 100644 --- a/tests/baselines/reference/user/debug.log +++ b/tests/baselines/reference/user/debug.log @@ -6,7 +6,7 @@ node_modules/debug/dist/debug.js(8,21): error TS2304: Cannot find name 'define'. node_modules/debug/dist/debug.js(8,46): error TS2304: Cannot find name 'define'. node_modules/debug/dist/debug.js(9,5): error TS2304: Cannot find name 'define'. node_modules/debug/dist/debug.js(33,33): error TS2554: Expected 1 arguments, but got 2. -node_modules/debug/dist/debug.js(34,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'true | NodeRequire' has no compatible call signatures. +node_modules/debug/dist/debug.js(34,27): error TS2554: Expected 1 arguments, but got 2. node_modules/debug/dist/debug.js(36,21): error TS2339: Property 'code' does not exist on type 'Error'. node_modules/debug/dist/debug.js(89,38): error TS2339: Property 'length' does not exist on type 'string | number'. Property 'length' does not exist on type 'number'. diff --git a/tests/baselines/reference/user/formik.log b/tests/baselines/reference/user/formik.log deleted file mode 100644 index 7daf2b6efee..00000000000 --- a/tests/baselines/reference/user/formik.log +++ /dev/null @@ -1,17 +0,0 @@ -Exit Code: 1 -Standard output: -index.tsx(30,17): error TS7006: Parameter 'values' implicitly has an 'any' type. -index.tsx(43,9): error TS7006: Parameter 'values' implicitly has an 'any' type. -index.tsx(44,11): error TS7031: Binding element 'setSubmitting' implicitly has an 'any' type. -index.tsx(44,26): error TS7031: Binding element 'setErrors' implicitly has an 'any' type. -index.tsx(60,9): error TS7031: Binding element 'values' implicitly has an 'any' type. -index.tsx(61,9): error TS7031: Binding element 'errors' implicitly has an 'any' type. -index.tsx(62,9): error TS7031: Binding element 'touched' implicitly has an 'any' type. -index.tsx(63,9): error TS7031: Binding element 'handleChange' implicitly has an 'any' type. -index.tsx(64,9): error TS7031: Binding element 'handleBlur' implicitly has an 'any' type. -index.tsx(65,9): error TS7031: Binding element 'handleSubmit' implicitly has an 'any' type. -index.tsx(66,9): error TS7031: Binding element 'isSubmitting' implicitly has an 'any' type. - - - -Standard error: diff --git a/tests/baselines/reference/user/graceful-fs.log b/tests/baselines/reference/user/graceful-fs.log index ac14b051d15..a0721706f16 100644 --- a/tests/baselines/reference/user/graceful-fs.log +++ b/tests/baselines/reference/user/graceful-fs.log @@ -12,14 +12,6 @@ node_modules/graceful-fs/graceful-fs.js(161,5): error TS2539: Cannot assign to ' node_modules/graceful-fs/graceful-fs.js(162,5): error TS2539: Cannot assign to 'WriteStream' because it is not a variable. node_modules/graceful-fs/graceful-fs.js(252,3): error TS2554: Expected 0 arguments, but got 3. node_modules/graceful-fs/graceful-fs.js(259,5): error TS2554: Expected 0 arguments, but got 3. -node_modules/graceful-fs/polyfills.js(7,24): error TS2339: Property 'env' does not exist on type 'typeof process'. -node_modules/graceful-fs/polyfills.js(7,60): error TS2339: Property 'platform' does not exist on type 'typeof process'. -node_modules/graceful-fs/polyfills.js(32,15): error TS2339: Property 'version' does not exist on type 'typeof process'. -node_modules/graceful-fs/polyfills.js(73,23): error TS2339: Property 'nextTick' does not exist on type 'typeof process'. -node_modules/graceful-fs/polyfills.js(79,23): error TS2339: Property 'nextTick' does not exist on type 'typeof process'. -node_modules/graceful-fs/polyfills.js(229,62): error TS2339: Property 'nextTick' does not exist on type 'typeof process'. -node_modules/graceful-fs/polyfills.js(323,26): error TS2339: Property 'getuid' does not exist on type 'typeof process'. -node_modules/graceful-fs/polyfills.js(323,44): error TS2339: Property 'getuid' does not exist on type 'typeof process'. diff --git a/tests/baselines/reference/user/jimp.log b/tests/baselines/reference/user/jimp.log index 2a11d85e4c5..40b0797489e 100644 --- a/tests/baselines/reference/user/jimp.log +++ b/tests/baselines/reference/user/jimp.log @@ -1,8 +1,8 @@ Exit Code: 1 Standard output: -node_modules/jimp/jimp.d.ts(487,12): error TS7010: 'appendConstructorOption', which lacks return-type annotation, implicitly has an 'any' return type. -node_modules/jimp/jimp.d.ts(529,12): error TS7010: 'measureText', which lacks return-type annotation, implicitly has an 'any' return type. -node_modules/jimp/jimp.d.ts(530,12): error TS7010: 'measureTextHeight', which lacks return-type annotation, implicitly has an 'any' return type. +node_modules/jimp/jimp.d.ts(497,12): error TS7010: 'appendConstructorOption', which lacks return-type annotation, implicitly has an 'any' return type. +node_modules/jimp/jimp.d.ts(539,12): error TS7010: 'measureText', which lacks return-type annotation, implicitly has an 'any' return type. +node_modules/jimp/jimp.d.ts(540,12): error TS7010: 'measureTextHeight', which lacks return-type annotation, implicitly has an 'any' return type. diff --git a/tests/baselines/reference/user/lodash.log b/tests/baselines/reference/user/lodash.log index 0551046aec1..383dcf9fe6f 100644 --- a/tests/baselines/reference/user/lodash.log +++ b/tests/baselines/reference/user/lodash.log @@ -150,7 +150,7 @@ node_modules/lodash/_memoizeCapped.js(22,22): error TS2339: Property 'cache' doe node_modules/lodash/_mergeData.js(60,26): error TS2554: Expected 4 arguments, but got 3. node_modules/lodash/_mergeData.js(67,26): error TS2554: Expected 4 arguments, but got 3. node_modules/lodash/_nodeUtil.js(7,80): error TS2339: Property 'nodeType' does not exist on type '{ "../../../tests/cases/user/lodash/node_modules/lodash/_nodeUtil": any; }'. -node_modules/lodash/_nodeUtil.js(13,47): error TS2339: Property 'process' does not exist on type 'boolean | Global'. +node_modules/lodash/_nodeUtil.js(13,47): error TS2339: Property 'process' does not exist on type 'false | Global'. Property 'process' does not exist on type 'false'. node_modules/lodash/_overRest.js(20,42): error TS2532: Object is possibly 'undefined'. node_modules/lodash/_overRest.js(24,27): error TS2532: Object is possibly 'undefined'. @@ -251,12 +251,12 @@ node_modules/lodash/debounce.js(86,30): error TS2532: Object is possibly 'undefi node_modules/lodash/debounce.js(111,23): error TS2532: Object is possibly 'undefined'. node_modules/lodash/debounce.js(125,65): error TS2532: Object is possibly 'undefined'. node_modules/lodash/deburr.js(42,44): error TS2345: Argument of type 'Function' is not assignable to parameter of type '(substring: string, ...args: any[]) => string'. -node_modules/lodash/difference.js(29,52): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. +node_modules/lodash/difference.js(29,52): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. -node_modules/lodash/differenceBy.js(40,52): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. +node_modules/lodash/differenceBy.js(40,52): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/differenceBy.js(40,78): error TS2554: Expected 0-1 arguments, but got 2. -node_modules/lodash/differenceWith.js(36,52): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. +node_modules/lodash/differenceWith.js(36,52): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/drop.js(13,10): error TS1003: Identifier expected. node_modules/lodash/drop.js(13,10): error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. @@ -273,42 +273,42 @@ node_modules/lodash/findIndex.js(52,31): error TS2554: Expected 0-1 arguments, b node_modules/lodash/findKey.js(41,30): error TS2554: Expected 0-1 arguments, but got 2. node_modules/lodash/findLastIndex.js(56,31): error TS2554: Expected 0-1 arguments, but got 2. node_modules/lodash/findLastKey.js(41,30): error TS2554: Expected 0-1 arguments, but got 2. -node_modules/lodash/fp/_baseConvert.js(144,5): error TS2559: Type 'Function' has no properties in common with type '{ cap?: boolean; curry?: boolean; fixed?: boolean; immutable?: boolean; rearg?: boolean; }'. -node_modules/lodash/fp/_baseConvert.js(145,5): error TS2322: Type 'string' is not assignable to type 'Function'. -node_modules/lodash/fp/_baseConvert.js(146,5): error TS2322: Type 'undefined' is not assignable to type 'string'. -node_modules/lodash/fp/_baseConvert.js(165,31): error TS2339: Property 'runInContext' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(184,21): error TS2339: Property 'ary' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(143,5): error TS2559: Type 'Function' has no properties in common with type '{ cap?: boolean; curry?: boolean; fixed?: boolean; immutable?: boolean; rearg?: boolean; }'. +node_modules/lodash/fp/_baseConvert.js(144,5): error TS2322: Type 'string' is not assignable to type 'Function'. +node_modules/lodash/fp/_baseConvert.js(145,5): error TS2322: Type 'undefined' is not assignable to type 'string'. +node_modules/lodash/fp/_baseConvert.js(164,31): error TS2339: Property 'runInContext' does not exist on type 'Function'. +node_modules/lodash/fp/_baseConvert.js(183,21): error TS2339: Property 'ary' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'ary' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(185,24): error TS2339: Property 'assign' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(184,24): error TS2339: Property 'assign' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'assign' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(186,23): error TS2339: Property 'clone' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(185,23): error TS2339: Property 'clone' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'clone' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(187,23): error TS2339: Property 'curry' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(186,23): error TS2339: Property 'curry' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'curry' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(188,22): error TS2339: Property 'forEach' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(187,22): error TS2339: Property 'forEach' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'forEach' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(189,25): error TS2339: Property 'isArray' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(188,25): error TS2339: Property 'isArray' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'isArray' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(190,25): error TS2339: Property 'isError' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(189,25): error TS2339: Property 'isError' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'isError' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(191,28): error TS2339: Property 'isFunction' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(190,28): error TS2339: Property 'isFunction' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'isFunction' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(192,27): error TS2339: Property 'isWeakMap' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(191,27): error TS2339: Property 'isWeakMap' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'isWeakMap' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(193,22): error TS2339: Property 'keys' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(192,22): error TS2339: Property 'keys' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'keys' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(194,23): error TS2339: Property 'rearg' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(193,23): error TS2339: Property 'rearg' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'rearg' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(195,27): error TS2339: Property 'toInteger' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(194,27): error TS2339: Property 'toInteger' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'toInteger' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(196,24): error TS2339: Property 'toPath' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. +node_modules/lodash/fp/_baseConvert.js(195,24): error TS2339: Property 'toPath' does not exist on type 'Function | { 'ary': any; 'assign': any; 'clone': any; 'curry': any; 'forEach': any; 'isArray': any; 'isError': any; 'isFunction': any; 'isWeakMap': any; 'iteratee': any; 'keys': any; 'rearg': any; 'toInteger': any; 'toPath': any; }'. Property 'toPath' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(263,57): error TS2345: Argument of type '{ cap?: boolean; curry?: boolean; fixed?: boolean; immutable?: boolean; rearg?: boolean; } | undefined' is not assignable to parameter of type 'Function'. +node_modules/lodash/fp/_baseConvert.js(262,57): error TS2345: Argument of type '{ cap?: boolean; curry?: boolean; fixed?: boolean; immutable?: boolean; rearg?: boolean; } | undefined' is not assignable to parameter of type 'Function'. Type 'undefined' is not assignable to type 'Function'. -node_modules/lodash/fp/_baseConvert.js(379,14): error TS2339: Property 'runInContext' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(516,33): error TS2339: Property 'placeholder' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(559,5): error TS2339: Property 'convert' does not exist on type 'Function'. -node_modules/lodash/fp/_baseConvert.js(561,7): error TS2339: Property 'placeholder' does not exist on type 'Function'. +node_modules/lodash/fp/_baseConvert.js(378,14): error TS2339: Property 'runInContext' does not exist on type 'Function'. +node_modules/lodash/fp/_baseConvert.js(513,31): error TS2339: Property 'placeholder' does not exist on type 'Function'. +node_modules/lodash/fp/_baseConvert.js(556,5): error TS2339: Property 'convert' does not exist on type 'Function'. +node_modules/lodash/fp/_baseConvert.js(557,5): error TS2339: Property 'placeholder' does not exist on type 'Function'. node_modules/lodash/fp/_convertBrowser.js(12,30): error TS2345: Argument of type 'Function' is not assignable to parameter of type 'string'. node_modules/lodash/fp/_convertBrowser.js(15,12): error TS2304: Cannot find name '_'. node_modules/lodash/fp/_convertBrowser.js(15,38): error TS2304: Cannot find name '_'. @@ -425,12 +425,12 @@ node_modules/lodash/truncate.js(78,16): error TS2454: Variable 'strSymbols' is u node_modules/lodash/truncate.js(85,7): error TS2454: Variable 'strSymbols' is used before being assigned. node_modules/lodash/unary.js(19,10): error TS2554: Expected 3 arguments, but got 2. node_modules/lodash/unescape.js(30,37): error TS2345: Argument of type 'Function' is not assignable to parameter of type '(substring: string, ...args: any[]) => string'. -node_modules/lodash/union.js(23,42): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. +node_modules/lodash/union.js(23,42): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. -node_modules/lodash/unionBy.js(36,42): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. +node_modules/lodash/unionBy.js(36,42): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/unionBy.js(36,68): error TS2554: Expected 0-1 arguments, but got 2. -node_modules/lodash/unionWith.js(31,42): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. +node_modules/lodash/unionWith.js(31,42): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/uniqBy.js(28,52): error TS2554: Expected 0-1 arguments, but got 2. node_modules/lodash/words.js(15,10): error TS1003: Identifier expected. diff --git a/tests/baselines/reference/user/npm.log b/tests/baselines/reference/user/npm.log index 920fae18b06..c9262f0f89a 100644 --- a/tests/baselines/reference/user/npm.log +++ b/tests/baselines/reference/user/npm.log @@ -1013,7 +1013,6 @@ node_modules/npm/test/network/registry.js(5,20): error TS2307: Cannot find modul node_modules/npm/test/network/registry.js(29,47): error TS2339: Property '_extend' does not exist on type 'typeof import("util")'. node_modules/npm/test/tap/00-check-mock-dep.js(12,20): error TS2732: Cannot find module 'npm-registry-mock/package.json'. Consider using '--resolveJsonModule' to import module with '.json' extension node_modules/npm/test/tap/00-check-mock-dep.js(13,19): error TS2732: Cannot find module '../../package.json'. Consider using '--resolveJsonModule' to import module with '.json' extension -node_modules/npm/test/tap/00-config-setup.js(23,39): error TS2339: Property 'HOME' does not exist on type 'typeof env'. node_modules/npm/test/tap/00-verify-bundle-deps.js(1,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/00-verify-bundle-deps.js(3,24): error TS2732: Cannot find module '../../package.json'. Consider using '--resolveJsonModule' to import module with '.json' extension node_modules/npm/test/tap/00-verify-ls-ok.js(2,20): error TS2307: Cannot find module 'tap'. @@ -1223,19 +1222,13 @@ node_modules/npm/test/tap/gist-shortcut.js(7,29): error TS2307: Cannot find modu node_modules/npm/test/tap/gist-shortcut.js(9,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/git-dependency-install-link.js(7,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/git-dependency-install-link.js(9,18): error TS2307: Cannot find module 'npm-registry-mock'. -node_modules/npm/test/tap/git-dependency-install-link.js(66,11): error TS2339: Property 'chdir' does not exist on type 'typeof process'. -node_modules/npm/test/tap/git-dependency-install-link.js(84,11): error TS2339: Property 'chdir' does not exist on type 'typeof process'. -node_modules/npm/test/tap/git-dependency-install-link.js(110,11): error TS2339: Property 'kill' does not exist on type 'typeof process'. node_modules/npm/test/tap/git-dependency-install-link.js(125,7): error TS2339: Property 'load' does not exist on type 'typeof EventEmitter'. -node_modules/npm/test/tap/git-dependency-install-link.js(175,11): error TS2339: Property 'chdir' does not exist on type 'typeof process'. node_modules/npm/test/tap/git-npmignore.js(7,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/git-npmignore.js(12,21): error TS2307: Cannot find module 'tacks'. node_modules/npm/test/tap/git-prepare.js(8,22): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/git-prepare.js(9,20): error TS2307: Cannot find module 'npm-registry-mock'. node_modules/npm/test/tap/git-prepare.js(19,21): error TS2307: Cannot find module 'tacks'. -node_modules/npm/test/tap/git-prepare.js(123,11): error TS2339: Property 'kill' does not exist on type 'typeof process'. node_modules/npm/test/tap/git-prepare.js(131,7): error TS2339: Property 'load' does not exist on type 'typeof EventEmitter'. -node_modules/npm/test/tap/git-prepare.js(179,11): error TS2339: Property 'chdir' does not exist on type 'typeof process'. node_modules/npm/test/tap/github-shortcut-package.js(7,29): error TS2307: Cannot find module 'require-inject'. node_modules/npm/test/tap/github-shortcut-package.js(9,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/github-shortcut.js(10,31): error TS2307: Cannot find module 'require-inject'. @@ -1287,7 +1280,6 @@ node_modules/npm/test/tap/install-duplicate-deps-warning.js(8,20): error TS2307: node_modules/npm/test/tap/install-from-local.js(7,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/install-into-likenamed-folder.js(6,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/install-link-scripts.js(7,20): error TS2307: Cannot find module 'tap'. -node_modules/npm/test/tap/install-link-scripts.js(130,11): error TS2339: Property 'chdir' does not exist on type 'typeof process'. node_modules/npm/test/tap/install-local-dep-cycle.js(6,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/install-man.js(7,20): error TS2307: Cannot find module 'tap'. node_modules/npm/test/tap/install-noargs-dev.js(5,18): error TS2307: Cannot find module 'npm-registry-mock'. diff --git a/tests/baselines/reference/user/uglify-js.log b/tests/baselines/reference/user/uglify-js.log index b34f83e350a..edb65213e6e 100644 --- a/tests/baselines/reference/user/uglify-js.log +++ b/tests/baselines/reference/user/uglify-js.log @@ -33,7 +33,7 @@ node_modules/uglify-js/lib/compress.js(3464,62): error TS2554: Expected 0 argume node_modules/uglify-js/lib/compress.js(3690,23): error TS2554: Expected 0 arguments, but got 1. node_modules/uglify-js/lib/compress.js(3711,24): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. node_modules/uglify-js/lib/compress.js(3721,28): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(3880,21): error TS2403: Subsequent variable declarations must have the same type. Variable 'defs' must be of type 'Dictionary & { set: (key: any, val: any) => any; add: (key: any, val: any) => any; get: (key: any) => any; del: (key: any) => any; has: (key: any) => boolean; each: (f: any) => void; size: () => any; map: (f: any) => any[]; clone: () => Dictionary & any; toObject: () => any; }', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(3880,21): error TS2403: Subsequent variable declarations must have the same type. Variable 'defs' must be of type 'Dictionary & { set: (key: any, val: any) => Dictionary & any; add: (key: any, val: any) => Dictionary & any; get: (key: any) => any; del: (key: any) => Dictionary & any; has: (key: any) => boolean; ... 4 more ...; toObject: () => any; }', but here has type 'any'. node_modules/uglify-js/lib/compress.js(3932,17): error TS2447: The '|=' operator is not allowed for boolean types. Consider using '||' instead. node_modules/uglify-js/lib/compress.js(3988,30): error TS2554: Expected 0 arguments, but got 1. node_modules/uglify-js/lib/compress.js(4097,18): error TS2554: Expected 0 arguments, but got 1. From 830b3877651d08f1844332c2f8cd89a9dc16ccf2 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 14:34:31 -0700 Subject: [PATCH 26/47] No longer specially recognize underscore and update baselines --- src/services/codefixes/convertToAsyncFunction.ts | 2 +- .../convertToAsyncFunction_IgnoreArgs1.ts | 2 +- .../convertToAsyncFunction/convertToAsyncFunction_Scope1.ts | 2 +- .../convertToAsyncFunction_runEffectfulContinuation.js | 2 +- .../convertToAsyncFunction_runEffectfulContinuation.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 54f8d99f724..69a0ef7e221 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -558,7 +558,7 @@ namespace ts.codefix { name = getMapEntryIfExists(funcNode); } - if (!name || name.identifier === undefined || name.identifier.text === "_" || name.identifier.text === "undefined") { + if (!name || name.identifier === undefined || name.identifier.text === "undefined") { return { identifier: createIdentifier(""), types, numberOfAssignmentsOriginal }; } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs1.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs1.ts index 2cb2ef5b32d..b3cef31ef8b 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs1.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs1.ts @@ -6,6 +6,6 @@ function /*[#|*/f/*|]*/(): Promise { // ==ASYNC FUNCTION::Convert to async function== async function f(): Promise { - await fetch('https://typescriptlang.org'); + const _ = await fetch('https://typescriptlang.org'); console.log("done"); } \ No newline at end of file diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Scope1.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Scope1.ts index 2ce31ce1dbf..ab7a707ddd0 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Scope1.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_Scope1.ts @@ -19,7 +19,7 @@ function /*[#|*/f/*|]*/() { async function f() { var var1: Response, var2; - await fetch('https://typescriptlang.org'); + const _ = await fetch('https://typescriptlang.org'); const res = await Promise.resolve(); var2 = "test"; const res_1 = await fetch("https://microsoft.com"); diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.js index bebd01f235a..4753c67cdae 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.js +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.js @@ -11,7 +11,7 @@ function res(result) { async function f() { const result = await fetch('https://typescriptlang.org'); - await res(result); + const _ = await res(result); return console.log("done"); } function res(result) { diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.ts index bebd01f235a..4753c67cdae 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_runEffectfulContinuation.ts @@ -11,7 +11,7 @@ function res(result) { async function f() { const result = await fetch('https://typescriptlang.org'); - await res(result); + const _ = await res(result); return console.log("done"); } function res(result) { From fc54a2c0a7cf31f9f149ee52ae809cdd1333ff00 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Sep 2018 15:00:41 -0700 Subject: [PATCH 27/47] Include triggerSpan in protocol.RenameInfo (#27160) --- src/server/protocol.ts | 3 +++ src/server/session.ts | 7 +++---- src/testRunner/unittests/tsserverProjectSystem.ts | 9 +++++++-- tests/baselines/reference/api/tsserverlibrary.d.ts | 4 +++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 2804b27deaf..1a4ee841014 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1123,6 +1123,9 @@ namespace ts.server.protocol { * Optional modifiers for the kind (such as 'public'). */ kindModifiers: string; + + /** Span of text to rename. */ + triggerSpan: TextSpan; } /** diff --git a/src/server/session.ts b/src/server/session.ts index 14ad20d7aae..977a0bd186d 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1161,13 +1161,12 @@ namespace ts.server { if (!simplifiedResult) return locations; const defaultProject = this.getDefaultProject(args); - const renameInfo = Session.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position)); + const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position), Debug.assertDefined(this.projectService.getScriptInfo(file))); return { info: renameInfo, locs: this.toSpanGroups(locations) }; } - // strips 'triggerSpan' - private static mapRenameInfo({ canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers }: RenameInfo): protocol.RenameInfo { - return { canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers }; + private mapRenameInfo({ canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers, triggerSpan }: RenameInfo, scriptInfo: ScriptInfo): protocol.RenameInfo { + return { canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers, triggerSpan: this.toLocationTextSpan(triggerSpan, scriptInfo) }; } private toSpanGroups(locations: ReadonlyArray): ReadonlyArray { diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index 40d79847baa..ba3df56b7f2 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -456,7 +456,7 @@ namespace ts.projectSystem { function protocolFileLocationFromSubstring(file: File, substring: string): protocol.FileLocationRequestArgs { return { file: file.path, ...protocolLocationFromSubstring(file.content, substring) }; } - function protocolFileSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions) { + function protocolFileSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): protocol.FileSpan { return { file: file.path, ...protocolTextSpanFromSubstring(file.content, substring, options) }; } function documentSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): DocumentSpan { @@ -8287,7 +8287,8 @@ namespace ts.projectSystem { protocolTextSpanFromSubstring(aFile.content, "C"), protocolTextSpanFromSubstring(aFile.content, "C", { index: 1 }), ]; - const cLocs: protocol.TextSpan[] = [protocolTextSpanFromSubstring(cFile.content, "C")]; + const span = protocolTextSpanFromSubstring(cFile.content, "C"); + const cLocs: protocol.TextSpan[] = [span]; assert.deepEqual(response, { info: { canRename: true, @@ -8296,6 +8297,7 @@ namespace ts.projectSystem { kind: ScriptElementKind.constElement, kindModifiers: ScriptElementKindModifier.exportedModifier, localizedErrorMessage: undefined, + triggerSpan: span, }, locs: [ { file: aFc, locs: cLocs }, @@ -10063,6 +10065,7 @@ declare class TestLib { kind: ScriptElementKind.alias, kindModifiers: ScriptElementKindModifier.none, localizedErrorMessage: undefined, + triggerSpan: protocolTextSpanFromSubstring(userTs.content, "fnA", { index: 1 }), }, locs: [renameUserTs(userTs), renameATs(aTs)], }); @@ -10081,6 +10084,7 @@ declare class TestLib { kind: ScriptElementKind.functionElement, kindModifiers: ScriptElementKindModifier.exportedModifier, localizedErrorMessage: undefined, + triggerSpan: protocolTextSpanFromSubstring(aTs.content, "fnA"), }, locs: [renameATs(aTs), renameUserTs(userTs)], }); @@ -10109,6 +10113,7 @@ declare class TestLib { kind: ScriptElementKind.alias, kindModifiers: ScriptElementKindModifier.none, localizedErrorMessage: undefined, + triggerSpan: protocolTextSpanFromSubstring(userTs.content, "fnB", { index: 1 }), }, locs: [ { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index cd590f8e76a..e9b896e9d17 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6455,6 +6455,8 @@ declare namespace ts.server.protocol { * Optional modifiers for the kind (such as 'public'). */ kindModifiers: string; + /** Span of text to rename. */ + triggerSpan: TextSpan; } /** * A group of text spans, all in 'file'. @@ -8733,7 +8735,7 @@ declare namespace ts.server { private getProjects; private getDefaultProject; private getRenameLocations; - private static mapRenameInfo; + private mapRenameInfo; private toSpanGroups; private getReferences; /** From bc709a87adde465c6c2bba450e60cdae4c712de1 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Sep 2018 15:14:09 -0700 Subject: [PATCH 28/47] Fix bug where array element is undefined (#26433) * Fix bug where array element is undefined * Better fix --- 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 78628da2749..75349ee8ef6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3470,8 +3470,8 @@ namespace ts { const arity = getTypeReferenceArity(type); const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context); const hasRestElement = (type.target).hasRestElement; - if (tupleConstituentNodes && tupleConstituentNodes.length > 0) { - for (let i = (type.target).minLength; i < arity; i++) { + if (tupleConstituentNodes) { + for (let i = (type.target).minLength; i < Math.min(arity, tupleConstituentNodes.length); i++) { tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ? createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) : createOptionalTypeNode(tupleConstituentNodes[i]); From c3b4f724984d70c50e504625d7e9c931837a590a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 17 Sep 2018 15:19:11 -0700 Subject: [PATCH 29/47] Improve indexed access inferences (#27015) --- src/compiler/checker.ts | 11 ++- .../voidReturnIndexUnionInference.js | 45 ++++++++++++ .../voidReturnIndexUnionInference.symbols | 68 +++++++++++++++++++ .../voidReturnIndexUnionInference.types | 61 +++++++++++++++++ .../compiler/voidReturnIndexUnionInference.ts | 24 +++++++ 5 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/voidReturnIndexUnionInference.js create mode 100644 tests/baselines/reference/voidReturnIndexUnionInference.symbols create mode 100644 tests/baselines/reference/voidReturnIndexUnionInference.types create mode 100644 tests/cases/compiler/voidReturnIndexUnionInference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 75349ee8ef6..31144ec5b50 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13373,7 +13373,7 @@ namespace ts { let propagationType: Type; inferFromTypes(originalSource, originalTarget); - function inferFromTypes(source: Type, target: Type) { + function inferFromTypes(source: Type, target: Type): void { if (!couldContainTypeVariables(target)) { return; } @@ -13541,7 +13541,14 @@ namespace ts { } else { if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) { - source = getApparentType(source); + const apparentSource = getApparentType(source); + // getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type. + // If that occurs and it doesn't simplify to an object or intersection, we'll need to restart `inferFromTypes` + // with the simplified source. + if (apparentSource !== source && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) { + return inferFromTypes(apparentSource, target); + } + source = apparentSource; } if (source.flags & (TypeFlags.Object | TypeFlags.Intersection)) { const key = source.id + "," + target.id; diff --git a/tests/baselines/reference/voidReturnIndexUnionInference.js b/tests/baselines/reference/voidReturnIndexUnionInference.js new file mode 100644 index 00000000000..01fcad76032 --- /dev/null +++ b/tests/baselines/reference/voidReturnIndexUnionInference.js @@ -0,0 +1,45 @@ +//// [voidReturnIndexUnionInference.ts] +// repro from https://github.com/Microsoft/TypeScript/issues/25274 +export function safeInvoke( + func: ((arg1: A1) => R) | null | undefined, + arg1: A1 +): R | undefined { + if (func) { + return func(arg1); + } else { + return undefined; + } +} + +interface Props { + onFoo?(value: string): boolean; + onBar?(value: string): void; +} + +function bad

(props: Readonly

) { + safeInvoke(props.onFoo, "blah"); + // ERROR HERE!!! + // Type R in signature of safeInvoke incorrectly inferred as {} instead of void! + safeInvoke(props.onBar, "blah"); +} + + +//// [voidReturnIndexUnionInference.js] +"use strict"; +exports.__esModule = true; +// repro from https://github.com/Microsoft/TypeScript/issues/25274 +function safeInvoke(func, arg1) { + if (func) { + return func(arg1); + } + else { + return undefined; + } +} +exports.safeInvoke = safeInvoke; +function bad(props) { + safeInvoke(props.onFoo, "blah"); + // ERROR HERE!!! + // Type R in signature of safeInvoke incorrectly inferred as {} instead of void! + safeInvoke(props.onBar, "blah"); +} diff --git a/tests/baselines/reference/voidReturnIndexUnionInference.symbols b/tests/baselines/reference/voidReturnIndexUnionInference.symbols new file mode 100644 index 00000000000..9a1cf9477d1 --- /dev/null +++ b/tests/baselines/reference/voidReturnIndexUnionInference.symbols @@ -0,0 +1,68 @@ +=== tests/cases/compiler/voidReturnIndexUnionInference.ts === +// repro from https://github.com/Microsoft/TypeScript/issues/25274 +export function safeInvoke( +>safeInvoke : Symbol(safeInvoke, Decl(voidReturnIndexUnionInference.ts, 0, 0)) +>A1 : Symbol(A1, Decl(voidReturnIndexUnionInference.ts, 1, 27)) +>R : Symbol(R, Decl(voidReturnIndexUnionInference.ts, 1, 30)) + + func: ((arg1: A1) => R) | null | undefined, +>func : Symbol(func, Decl(voidReturnIndexUnionInference.ts, 1, 34)) +>arg1 : Symbol(arg1, Decl(voidReturnIndexUnionInference.ts, 2, 12)) +>A1 : Symbol(A1, Decl(voidReturnIndexUnionInference.ts, 1, 27)) +>R : Symbol(R, Decl(voidReturnIndexUnionInference.ts, 1, 30)) + + arg1: A1 +>arg1 : Symbol(arg1, Decl(voidReturnIndexUnionInference.ts, 2, 47)) +>A1 : Symbol(A1, Decl(voidReturnIndexUnionInference.ts, 1, 27)) + +): R | undefined { +>R : Symbol(R, Decl(voidReturnIndexUnionInference.ts, 1, 30)) + + if (func) { +>func : Symbol(func, Decl(voidReturnIndexUnionInference.ts, 1, 34)) + + return func(arg1); +>func : Symbol(func, Decl(voidReturnIndexUnionInference.ts, 1, 34)) +>arg1 : Symbol(arg1, Decl(voidReturnIndexUnionInference.ts, 2, 47)) + + } else { + return undefined; +>undefined : Symbol(undefined) + } +} + +interface Props { +>Props : Symbol(Props, Decl(voidReturnIndexUnionInference.ts, 10, 1)) + + onFoo?(value: string): boolean; +>onFoo : Symbol(Props.onFoo, Decl(voidReturnIndexUnionInference.ts, 12, 17)) +>value : Symbol(value, Decl(voidReturnIndexUnionInference.ts, 13, 11)) + + onBar?(value: string): void; +>onBar : Symbol(Props.onBar, Decl(voidReturnIndexUnionInference.ts, 13, 35)) +>value : Symbol(value, Decl(voidReturnIndexUnionInference.ts, 14, 11)) +} + +function bad

(props: Readonly

) { +>bad : Symbol(bad, Decl(voidReturnIndexUnionInference.ts, 15, 1)) +>P : Symbol(P, Decl(voidReturnIndexUnionInference.ts, 17, 13)) +>Props : Symbol(Props, Decl(voidReturnIndexUnionInference.ts, 10, 1)) +>props : Symbol(props, Decl(voidReturnIndexUnionInference.ts, 17, 30)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(voidReturnIndexUnionInference.ts, 17, 13)) + + safeInvoke(props.onFoo, "blah"); +>safeInvoke : Symbol(safeInvoke, Decl(voidReturnIndexUnionInference.ts, 0, 0)) +>props.onFoo : Symbol(onFoo, Decl(voidReturnIndexUnionInference.ts, 12, 17)) +>props : Symbol(props, Decl(voidReturnIndexUnionInference.ts, 17, 30)) +>onFoo : Symbol(onFoo, Decl(voidReturnIndexUnionInference.ts, 12, 17)) + + // ERROR HERE!!! + // Type R in signature of safeInvoke incorrectly inferred as {} instead of void! + safeInvoke(props.onBar, "blah"); +>safeInvoke : Symbol(safeInvoke, Decl(voidReturnIndexUnionInference.ts, 0, 0)) +>props.onBar : Symbol(onBar, Decl(voidReturnIndexUnionInference.ts, 13, 35)) +>props : Symbol(props, Decl(voidReturnIndexUnionInference.ts, 17, 30)) +>onBar : Symbol(onBar, Decl(voidReturnIndexUnionInference.ts, 13, 35)) +} + diff --git a/tests/baselines/reference/voidReturnIndexUnionInference.types b/tests/baselines/reference/voidReturnIndexUnionInference.types new file mode 100644 index 00000000000..20a962b9fef --- /dev/null +++ b/tests/baselines/reference/voidReturnIndexUnionInference.types @@ -0,0 +1,61 @@ +=== tests/cases/compiler/voidReturnIndexUnionInference.ts === +// repro from https://github.com/Microsoft/TypeScript/issues/25274 +export function safeInvoke( +>safeInvoke : (func: ((arg1: A1) => R) | null | undefined, arg1: A1) => R | undefined + + func: ((arg1: A1) => R) | null | undefined, +>func : ((arg1: A1) => R) | null | undefined +>arg1 : A1 +>null : null + + arg1: A1 +>arg1 : A1 + +): R | undefined { + if (func) { +>func : ((arg1: A1) => R) | null | undefined + + return func(arg1); +>func(arg1) : R +>func : (arg1: A1) => R +>arg1 : A1 + + } else { + return undefined; +>undefined : undefined + } +} + +interface Props { + onFoo?(value: string): boolean; +>onFoo : ((value: string) => boolean) | undefined +>value : string + + onBar?(value: string): void; +>onBar : ((value: string) => void) | undefined +>value : string +} + +function bad

(props: Readonly

) { +>bad :

(props: Readonly

) => void +>props : Readonly

+ + safeInvoke(props.onFoo, "blah"); +>safeInvoke(props.onFoo, "blah") : boolean | undefined +>safeInvoke : (func: ((arg1: A1) => R) | null | undefined, arg1: A1) => R | undefined +>props.onFoo : P["onFoo"] +>props : Readonly

+>onFoo : P["onFoo"] +>"blah" : "blah" + + // ERROR HERE!!! + // Type R in signature of safeInvoke incorrectly inferred as {} instead of void! + safeInvoke(props.onBar, "blah"); +>safeInvoke(props.onBar, "blah") : void | undefined +>safeInvoke : (func: ((arg1: A1) => R) | null | undefined, arg1: A1) => R | undefined +>props.onBar : P["onBar"] +>props : Readonly

+>onBar : P["onBar"] +>"blah" : "blah" +} + diff --git a/tests/cases/compiler/voidReturnIndexUnionInference.ts b/tests/cases/compiler/voidReturnIndexUnionInference.ts new file mode 100644 index 00000000000..e2dd5ac6c72 --- /dev/null +++ b/tests/cases/compiler/voidReturnIndexUnionInference.ts @@ -0,0 +1,24 @@ +// @strict: true +// repro from https://github.com/Microsoft/TypeScript/issues/25274 +export function safeInvoke( + func: ((arg1: A1) => R) | null | undefined, + arg1: A1 +): R | undefined { + if (func) { + return func(arg1); + } else { + return undefined; + } +} + +interface Props { + onFoo?(value: string): boolean; + onBar?(value: string): void; +} + +function bad

(props: Readonly

) { + safeInvoke(props.onFoo, "blah"); + // ERROR HERE!!! + // Type R in signature of safeInvoke incorrectly inferred as {} instead of void! + safeInvoke(props.onBar, "blah"); +} From a55c0b7df991fbc458d094c891070972e1ff7b8b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 17 Sep 2018 15:19:23 -0700 Subject: [PATCH 30/47] Allow drawing inferences to conditional type branches (#27012) * Allow drawing inferences to conditional type branches * Fix lint --- src/compiler/checker.ts | 5 +- .../extractInferenceImprovement.errors.txt | 38 ++++++++ .../reference/extractInferenceImprovement.js | 48 +++++++++++ .../extractInferenceImprovement.symbols | 86 +++++++++++++++++++ .../extractInferenceImprovement.types | 82 ++++++++++++++++++ .../compiler/extractInferenceImprovement.ts | 29 +++++++ 6 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/extractInferenceImprovement.errors.txt create mode 100644 tests/baselines/reference/extractInferenceImprovement.js create mode 100644 tests/baselines/reference/extractInferenceImprovement.symbols create mode 100644 tests/baselines/reference/extractInferenceImprovement.types create mode 100644 tests/cases/compiler/extractInferenceImprovement.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 31144ec5b50..6d400b99e8a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13508,6 +13508,9 @@ namespace ts { inferFromTypes(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target)); inferFromTypes(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target)); } + else if (target.flags & TypeFlags.Conditional) { + inferFromTypes(source, getUnionType([getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)])); + } else if (target.flags & TypeFlags.UnionOrIntersection) { const targetTypes = (target).types; let typeVariableCount = 0; @@ -13754,7 +13757,7 @@ namespace ts { function hasPrimitiveConstraint(type: TypeParameter): boolean { const constraint = getConstraintOfTypeParameter(type); - return !!constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index); + return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, TypeFlags.Primitive | TypeFlags.Index); } function isObjectLiteralType(type: Type) { diff --git a/tests/baselines/reference/extractInferenceImprovement.errors.txt b/tests/baselines/reference/extractInferenceImprovement.errors.txt new file mode 100644 index 00000000000..b3582f6b022 --- /dev/null +++ b/tests/baselines/reference/extractInferenceImprovement.errors.txt @@ -0,0 +1,38 @@ +tests/cases/compiler/extractInferenceImprovement.ts(26,26): error TS2345: Argument of type 'unique symbol' is not assignable to parameter of type 'never'. +tests/cases/compiler/extractInferenceImprovement.ts(28,26): error TS2345: Argument of type 'unique symbol' is not assignable to parameter of type '"first" | "second"'. + + +==== tests/cases/compiler/extractInferenceImprovement.ts (2 errors) ==== + // repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 + function getProperty2(obj: T, key: Extract): T[K] { + return obj[key]; + } + + function getProperty3>(obj: T, key: K): T[K] { + return obj[key]; + } + + const s = Symbol(); + interface StrNum { + first: string; + second: number; + [s]: string; + } + const obj: StrNum = {} as any; + + let prop: string; + + // should work + prop = getProperty2(obj, 'first'); + + prop = getProperty3(obj, 'first'); + + // Should fail + prop = getProperty2(obj, s); + ~ +!!! error TS2345: Argument of type 'unique symbol' is not assignable to parameter of type 'never'. + + prop = getProperty3(obj, s); + ~ +!!! error TS2345: Argument of type 'unique symbol' is not assignable to parameter of type '"first" | "second"'. + \ No newline at end of file diff --git a/tests/baselines/reference/extractInferenceImprovement.js b/tests/baselines/reference/extractInferenceImprovement.js new file mode 100644 index 00000000000..c377d3141d9 --- /dev/null +++ b/tests/baselines/reference/extractInferenceImprovement.js @@ -0,0 +1,48 @@ +//// [extractInferenceImprovement.ts] +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj: T, key: Extract): T[K] { + return obj[key]; +} + +function getProperty3>(obj: T, key: K): T[K] { + return obj[key]; +} + +const s = Symbol(); +interface StrNum { + first: string; + second: number; + [s]: string; +} +const obj: StrNum = {} as any; + +let prop: string; + +// should work +prop = getProperty2(obj, 'first'); + +prop = getProperty3(obj, 'first'); + +// Should fail +prop = getProperty2(obj, s); + +prop = getProperty3(obj, s); + + +//// [extractInferenceImprovement.js] +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj, key) { + return obj[key]; +} +function getProperty3(obj, key) { + return obj[key]; +} +const s = Symbol(); +const obj = {}; +let prop; +// should work +prop = getProperty2(obj, 'first'); +prop = getProperty3(obj, 'first'); +// Should fail +prop = getProperty2(obj, s); +prop = getProperty3(obj, s); diff --git a/tests/baselines/reference/extractInferenceImprovement.symbols b/tests/baselines/reference/extractInferenceImprovement.symbols new file mode 100644 index 00000000000..39977a99e7b --- /dev/null +++ b/tests/baselines/reference/extractInferenceImprovement.symbols @@ -0,0 +1,86 @@ +=== tests/cases/compiler/extractInferenceImprovement.ts === +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj: T, key: Extract): T[K] { +>getProperty2 : Symbol(getProperty2, Decl(extractInferenceImprovement.ts, 0, 0)) +>T : Symbol(T, Decl(extractInferenceImprovement.ts, 1, 22)) +>K : Symbol(K, Decl(extractInferenceImprovement.ts, 1, 24)) +>T : Symbol(T, Decl(extractInferenceImprovement.ts, 1, 22)) +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 1, 44)) +>T : Symbol(T, Decl(extractInferenceImprovement.ts, 1, 22)) +>key : Symbol(key, Decl(extractInferenceImprovement.ts, 1, 51)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>K : Symbol(K, Decl(extractInferenceImprovement.ts, 1, 24)) +>T : Symbol(T, Decl(extractInferenceImprovement.ts, 1, 22)) +>K : Symbol(K, Decl(extractInferenceImprovement.ts, 1, 24)) + + return obj[key]; +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 1, 44)) +>key : Symbol(key, Decl(extractInferenceImprovement.ts, 1, 51)) +} + +function getProperty3>(obj: T, key: K): T[K] { +>getProperty3 : Symbol(getProperty3, Decl(extractInferenceImprovement.ts, 3, 1)) +>T : Symbol(T, Decl(extractInferenceImprovement.ts, 5, 22)) +>K : Symbol(K, Decl(extractInferenceImprovement.ts, 5, 24)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(extractInferenceImprovement.ts, 5, 22)) +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 5, 61)) +>T : Symbol(T, Decl(extractInferenceImprovement.ts, 5, 22)) +>key : Symbol(key, Decl(extractInferenceImprovement.ts, 5, 68)) +>K : Symbol(K, Decl(extractInferenceImprovement.ts, 5, 24)) +>T : Symbol(T, Decl(extractInferenceImprovement.ts, 5, 22)) +>K : Symbol(K, Decl(extractInferenceImprovement.ts, 5, 24)) + + return obj[key]; +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 5, 61)) +>key : Symbol(key, Decl(extractInferenceImprovement.ts, 5, 68)) +} + +const s = Symbol(); +>s : Symbol(s, Decl(extractInferenceImprovement.ts, 9, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +interface StrNum { +>StrNum : Symbol(StrNum, Decl(extractInferenceImprovement.ts, 9, 19)) + + first: string; +>first : Symbol(StrNum.first, Decl(extractInferenceImprovement.ts, 10, 18)) + + second: number; +>second : Symbol(StrNum.second, Decl(extractInferenceImprovement.ts, 11, 18)) + + [s]: string; +>[s] : Symbol(StrNum[s], Decl(extractInferenceImprovement.ts, 12, 19)) +>s : Symbol(s, Decl(extractInferenceImprovement.ts, 9, 5)) +} +const obj: StrNum = {} as any; +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5)) +>StrNum : Symbol(StrNum, Decl(extractInferenceImprovement.ts, 9, 19)) + +let prop: string; +>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3)) + +// should work +prop = getProperty2(obj, 'first'); +>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3)) +>getProperty2 : Symbol(getProperty2, Decl(extractInferenceImprovement.ts, 0, 0)) +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5)) + +prop = getProperty3(obj, 'first'); +>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3)) +>getProperty3 : Symbol(getProperty3, Decl(extractInferenceImprovement.ts, 3, 1)) +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5)) + +// Should fail +prop = getProperty2(obj, s); +>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3)) +>getProperty2 : Symbol(getProperty2, Decl(extractInferenceImprovement.ts, 0, 0)) +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5)) +>s : Symbol(s, Decl(extractInferenceImprovement.ts, 9, 5)) + +prop = getProperty3(obj, s); +>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3)) +>getProperty3 : Symbol(getProperty3, Decl(extractInferenceImprovement.ts, 3, 1)) +>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5)) +>s : Symbol(s, Decl(extractInferenceImprovement.ts, 9, 5)) + diff --git a/tests/baselines/reference/extractInferenceImprovement.types b/tests/baselines/reference/extractInferenceImprovement.types new file mode 100644 index 00000000000..0e18dc30ee0 --- /dev/null +++ b/tests/baselines/reference/extractInferenceImprovement.types @@ -0,0 +1,82 @@ +=== tests/cases/compiler/extractInferenceImprovement.ts === +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj: T, key: Extract): T[K] { +>getProperty2 : (obj: T, key: Extract) => T[K] +>obj : T +>key : Extract + + return obj[key]; +>obj[key] : T[Extract] +>obj : T +>key : Extract +} + +function getProperty3>(obj: T, key: K): T[K] { +>getProperty3 : >(obj: T, key: K) => T[K] +>obj : T +>key : K + + return obj[key]; +>obj[key] : T[K] +>obj : T +>key : K +} + +const s = Symbol(); +>s : unique symbol +>Symbol() : unique symbol +>Symbol : SymbolConstructor + +interface StrNum { + first: string; +>first : string + + second: number; +>second : number + + [s]: string; +>[s] : string +>s : unique symbol +} +const obj: StrNum = {} as any; +>obj : StrNum +>{} as any : any +>{} : {} + +let prop: string; +>prop : string + +// should work +prop = getProperty2(obj, 'first'); +>prop = getProperty2(obj, 'first') : string +>prop : string +>getProperty2(obj, 'first') : string +>getProperty2 : (obj: T, key: Extract) => T[K] +>obj : StrNum +>'first' : "first" + +prop = getProperty3(obj, 'first'); +>prop = getProperty3(obj, 'first') : string +>prop : string +>getProperty3(obj, 'first') : string +>getProperty3 : >(obj: T, key: K) => T[K] +>obj : StrNum +>'first' : "first" + +// Should fail +prop = getProperty2(obj, s); +>prop = getProperty2(obj, s) : any +>prop : string +>getProperty2(obj, s) : any +>getProperty2 : (obj: T, key: Extract) => T[K] +>obj : StrNum +>s : unique symbol + +prop = getProperty3(obj, s); +>prop = getProperty3(obj, s) : any +>prop : string +>getProperty3(obj, s) : any +>getProperty3 : >(obj: T, key: K) => T[K] +>obj : StrNum +>s : unique symbol + diff --git a/tests/cases/compiler/extractInferenceImprovement.ts b/tests/cases/compiler/extractInferenceImprovement.ts new file mode 100644 index 00000000000..f70e6c07e86 --- /dev/null +++ b/tests/cases/compiler/extractInferenceImprovement.ts @@ -0,0 +1,29 @@ +// @target: es6 +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj: T, key: Extract): T[K] { + return obj[key]; +} + +function getProperty3>(obj: T, key: K): T[K] { + return obj[key]; +} + +const s = Symbol(); +interface StrNum { + first: string; + second: number; + [s]: string; +} +const obj: StrNum = {} as any; + +let prop: string; + +// should work +prop = getProperty2(obj, 'first'); + +prop = getProperty3(obj, 'first'); + +// Should fail +prop = getProperty2(obj, s); + +prop = getProperty3(obj, s); From 4e3e8f5ea718e0864cce0b03efa388c7f52b2bcd Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Sep 2018 15:23:44 -0700 Subject: [PATCH 31/47] convertToAsyncFunction: Reduce casts in getTransformationBody (#27158) --- .../codefixes/convertToAsyncFunction.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 8bd8341264a..fc045381f5f 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -402,7 +402,7 @@ namespace ts.codefix { } // should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts - function getTransformationBody(func: Node, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier, parent: CallExpression, transformer: Transformer): NodeArray { + function getTransformationBody(func: Expression, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier, parent: CallExpression, transformer: Transformer): NodeArray { const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0; const hasArgName = argName && argName.identifier.text.length > 0; @@ -429,15 +429,15 @@ namespace ts.codefix { prevArgName!.types.push(returnType!); return varDeclOrAssignment; - case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: + case SyntaxKind.ArrowFunction: { + const funcBody = (func as FunctionExpression | ArrowFunction).body; // Arrow functions with block bodies { } will enter this control flow - if (isFunctionLikeDeclaration(func) && func.body && isBlock(func.body) && func.body.statements) { + if (isBlock(funcBody)) { let refactoredStmts: Statement[] = []; let seenReturnStatement = false; - for (const statement of func.body.statements) { + for (const statement of funcBody.statements) { if (isReturnStatement(statement)) { seenReturnStatement = true; } @@ -454,8 +454,7 @@ namespace ts.codefix { removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer.constIdentifiers, seenReturnStatement); } else { - const funcBody = (func).body; - const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody as Expression)); + const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody)); const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName); if (innerCbBody.length > 0) { @@ -465,14 +464,15 @@ namespace ts.codefix { if (hasPrevArgName && !shouldReturn) { const type = transformer.checker.getTypeAtLocation(func); const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType(); - const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, getSynthesizedDeepClone(funcBody) as Expression, transformer); + const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, getSynthesizedDeepClone(funcBody), transformer); prevArgName!.types.push(returnType); return varDeclOrAssignment; } else { - return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody) as Expression)]); + return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody))]); } } + } default: // We've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code. codeActionSucceeded = false; From cfd0a62357b39e2d70213dde6ee7985245748309 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 17 Sep 2018 15:26:41 -0700 Subject: [PATCH 32/47] When renaming module, ensure rename span is just the last component of the path (#27151) --- src/compiler/diagnosticMessages.json | 4 ++++ src/services/rename.ts | 9 ++++++++- .../findAllRefs_importType_exportEquals.ts | 8 ++++---- tests/cases/fourslash/renameImport.ts | 17 ++++++++++++----- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5805e2d88d0..42c594c19b0 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4145,6 +4145,10 @@ "category": "Error", "code": 8030 }, + "You cannot rename a module via a global import.": { + "category": "Error", + "code": 8031 + }, "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": { "category": "Error", "code": 9002 diff --git a/src/services/rename.ts b/src/services/rename.ts index 649ed33786f..d7f23347cb4 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -39,11 +39,18 @@ namespace ts.Rename { } function getRenameInfoForModule(node: StringLiteralLike, sourceFile: SourceFile, moduleSymbol: Symbol): RenameInfo | undefined { + if (!isExternalModuleNameRelative(node.text)) { + return getRenameInfoError(Diagnostics.You_cannot_rename_a_module_via_a_global_import); + } + const moduleSourceFile = find(moduleSymbol.declarations, isSourceFile); if (!moduleSourceFile) return undefined; const withoutIndex = node.text.endsWith("/index") || node.text.endsWith("/index.js") ? undefined : tryRemoveSuffix(removeFileExtension(moduleSourceFile.fileName), "/index"); const name = withoutIndex === undefined ? moduleSourceFile.fileName : withoutIndex; const kind = withoutIndex === undefined ? ScriptElementKind.moduleElement : ScriptElementKind.directory; + const indexAfterLastSlash = node.text.lastIndexOf("/") + 1; + // Span should only be the last component of the path. + 1 to account for the quote character. + const triggerSpan = createTextSpan(node.getStart(sourceFile) + 1 + indexAfterLastSlash, node.text.length - indexAfterLastSlash); return { canRename: true, fileToRename: name, @@ -52,7 +59,7 @@ namespace ts.Rename { localizedErrorMessage: undefined, fullDisplayName: name, kindModifiers: ScriptElementKindModifier.none, - triggerSpan: createTriggerSpanForNode(node, sourceFile), + triggerSpan, }; } diff --git a/tests/cases/fourslash/findAllRefs_importType_exportEquals.ts b/tests/cases/fourslash/findAllRefs_importType_exportEquals.ts index 04b3c212dfc..7fe0696f952 100644 --- a/tests/cases/fourslash/findAllRefs_importType_exportEquals.ts +++ b/tests/cases/fourslash/findAllRefs_importType_exportEquals.ts @@ -8,12 +8,12 @@ ////export = [|T|]; // @Filename: /b.ts -////const x: import("[|./a|]") = 0; -////const y: import("[|./a|]").U = ""; +////const x: import("[|./[|a|]|]") = 0; +////const y: import("[|./[|a|]|]").U = ""; verify.noErrors(); -const [r0, r1, r2, r3, r4] = test.ranges(); +const [r0, r1, r2, r3, r3b, r4, r4b] = test.ranges(); verify.referenceGroups(r0, [{ definition: "type T = number\nnamespace T", ranges: [r0, r2, r3] }]); verify.referenceGroups(r1, [{ definition: "namespace T", ranges: [r1, r2] }]); verify.referenceGroups(r2, [{ definition: "type T = number\nnamespace T", ranges: [r0, r1, r2, r3] }]); @@ -25,7 +25,7 @@ verify.referenceGroups([r3, r4], [ verify.renameLocations(r0, [r0, r2]); verify.renameLocations(r1, [r1, r2]); verify.renameLocations(r2, [r0, r1, r2]); -for (const range of [r3, r4]) { +for (const range of [r3b, r4b]) { goTo.rangeStart(range); verify.renameInfoSucceeded(/*displayName*/ "/a.ts", /*fullDisplayName*/ "/a.ts", /*kind*/ "module", /*kindModifiers*/ "", /*fileToRename*/ "/a.ts", range); } diff --git a/tests/cases/fourslash/renameImport.ts b/tests/cases/fourslash/renameImport.ts index f3221f3584e..6fdef347205 100644 --- a/tests/cases/fourslash/renameImport.ts +++ b/tests/cases/fourslash/renameImport.ts @@ -2,6 +2,9 @@ // @allowJs: true +// @Filename: /node_modules/global/index.d.ts +////export const x: number; + // @Filename: /a.ts ////export const x = 0; @@ -9,13 +12,14 @@ ////export const x = 0; // @Filename: /b.ts -////import * as a from "[|./a|]"; -////import a2 = require("[|./a|]"); -////import * as dir from "[|{| "target": "dir" |}./dir|]"; -////import * as dir2 from "[|{| "target": "dir/index" |}./dir/index|]"; +////import * as a from "./[|a|]"; +////import a2 = require("./[|a|]"); +////import * as dir from "./[|{| "target": "dir" |}dir|]"; +////import * as dir2 from "./dir/[|{| "target": "dir/index" |}index|]"; // @Filename: /c.js -////const a = require("[|./a|]"); +////const a = require("./[|a|]"); +////const global = require("/*global*/global"); verify.noErrors(); goTo.eachRange(range => { @@ -24,3 +28,6 @@ goTo.eachRange(range => { const kind = target === "dir" ? "directory" : "module"; verify.renameInfoSucceeded(/*displayName*/ name, /*fullDisplayName*/ name, /*kind*/ kind, /*kindModifiers*/ "", /*fileToRename*/ name, range); }); + +goTo.marker("global"); +verify.renameInfoFailed("You cannot rename a module via a global import."); From 1a3ff452c1d8a9f2974297b5e87e35f6d38ae996 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 15:44:08 -0700 Subject: [PATCH 33/47] Respond to CR --- .../codefixes/convertToAsyncFunction.ts | 21 +++++++------------ .../unittests/convertToAsyncFunction.ts | 11 ++++++++++ .../convertToAsyncFunction_nestedPromises.js | 13 ++++++++++++ .../convertToAsyncFunction_nestedPromises.ts | 13 ++++++++++++ 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_nestedPromises.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_nestedPromises.ts diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 69a0ef7e221..910cceadcfb 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -14,17 +14,10 @@ namespace ts.codefix { getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => convertToAsyncFunction(changes, err.file, err.start, context.program.getTypeChecker(), context)), }); - - /* - custom type to encapsulate information for variable declarations synthesized in the refactor - numberOfUsesOriginal - number of times the variable should be assigned in the refactor - numberOfUsesSynthesized - count of how many times the variable has been assigned so far - At the end of the refactor, numberOfUsesOriginal should === numberOfUsesSynthesized - */ interface SynthIdentifier { identifier: Identifier; types: Type[]; - numberOfAssignmentsOriginal: number; + numberOfAssignmentsOriginal: number; // number of times the variable should be assigned in the refactor } interface SymbolAndIdentifier { @@ -380,7 +373,7 @@ namespace ts.codefix { const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0; const originalNodeParent = node.original ? node.original.parent : node.parent; if (hasPrevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { - return createVariableDeclarationOrAssignment(prevArgName!, createAwait(node), transformer).concat(); // hack to make the types match + return createTransformedStatement(prevArgName!, createAwait(node), transformer).concat(); // hack to make the types match } else if (!hasPrevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { return [createStatement(createAwait(node))]; @@ -389,7 +382,7 @@ namespace ts.codefix { return [createReturn(getSynthesizedDeepClone(node))]; } - function createVariableDeclarationOrAssignment(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): NodeArray { + function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): NodeArray { if (!prevArgName || prevArgName.identifier.text.length === 0) { // if there's no argName to assign to, there still might be side effects return createNodeArray([createStatement(rightHandSide)]); @@ -429,7 +422,7 @@ namespace ts.codefix { break; } const returnType = callSignatures[0].getReturnType(); - const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName, createAwait(synthCall), transformer); + const varDeclOrAssignment = createTransformedStatement(prevArgName, createAwait(synthCall), transformer); if (prevArgName) { prevArgName.types.push(returnType); } @@ -471,12 +464,12 @@ namespace ts.codefix { const type = transformer.checker.getTypeAtLocation(func); const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType(); const rightHandSide = getSynthesizedDeepClone(funcBody); - const possiblyAwaitedRightHandSide = isPromiseReturningExpression(funcBody, transformer.checker) ? createAwait(rightHandSide) : rightHandSide; - const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName, possiblyAwaitedRightHandSide, transformer); + const possiblyAwaitedRightHandSide = !!transformer.checker.getPromisedTypeOfPromise(returnType) ? createAwait(rightHandSide) : rightHandSide; + const transformedStatement = createTransformedStatement(prevArgName, possiblyAwaitedRightHandSide, transformer); if (prevArgName) { prevArgName.types.push(returnType); } - return varDeclOrAssignment; + return transformedStatement; } else { return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody))]); diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index 3f8032275f5..d7e70e4d1e5 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -414,6 +414,11 @@ function [#|f|](): Promise { _testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs2", ` function [#|f|](): Promise { return fetch('https://typescriptlang.org').then( () => console.log("done") ); +}` + ); + _testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs3", ` +function [#|f|](): Promise { + return fetch('https://typescriptlang.org').then( () => console.log("almost done") ).then( () => console.log("done") ); }` ); _testConvertToAsyncFunction("convertToAsyncFunction_Method", ` @@ -1216,6 +1221,12 @@ function [#|f|]() { } `); + +_testConvertToAsyncFunction("convertToAsyncFunction_nestedPromises", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y))); +} +`); }); function _testConvertToAsyncFunction(caption: string, text: string) { diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_nestedPromises.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_nestedPromises.js new file mode 100644 index 00000000000..3ce5c421c3d --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_nestedPromises.js @@ -0,0 +1,13 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y))); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const x = await fetch('https://typescriptlang.org'); + const y = await Promise.resolve(3); + return Promise.resolve(x.statusText.length + y); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_nestedPromises.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_nestedPromises.ts new file mode 100644 index 00000000000..3ce5c421c3d --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_nestedPromises.ts @@ -0,0 +1,13 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y))); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const x = await fetch('https://typescriptlang.org'); + const y = await Promise.resolve(3); + return Promise.resolve(x.statusText.length + y); +} From e90679ce6bbfa18a6416103a4b6e71729c02c7c8 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 15:52:59 -0700 Subject: [PATCH 34/47] Add baseline --- .../convertToAsyncFunction_IgnoreArgs3.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs3.ts diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs3.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs3.ts new file mode 100644 index 00000000000..60cc408a8f5 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs3.ts @@ -0,0 +1,12 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/(): Promise { + return fetch('https://typescriptlang.org').then( () => console.log("almost done") ).then( () => console.log("done") ); +} +// ==ASYNC FUNCTION::Convert to async function== + +async function f(): Promise { + await fetch('https://typescriptlang.org'); + console.log("almost done"); + return console.log("done"); +} \ No newline at end of file From 099586937751ae4ced5b3471804d6bf760b8e11f Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 15:53:15 -0700 Subject: [PATCH 35/47] Stop creating empty identifier name --- .../codefixes/convertToAsyncFunction.ts | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 910cceadcfb..b9b5fe150d5 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -311,7 +311,7 @@ namespace ts.codefix { const tryBlock = createBlock(transformExpression(node.expression, transformer, node, prevArgName)); const transformationBody = getTransformationBody(func, prevArgName, argName, node, transformer); - const catchArg = argName.identifier.text.length > 0 ? argName.identifier.text : "e"; + const catchArg = argName ? argName.identifier.text : "e"; const catchClause = createCatchClause(catchArg, createBlock(transformationBody)); /* @@ -353,7 +353,7 @@ namespace ts.codefix { const transformationBody2 = getTransformationBody(rej, prevArgName, argNameRej, node, transformer); - const catchArg = argNameRej.identifier.text.length > 0 ? argNameRej.identifier.text : "e"; + const catchArg = argNameRej ? argNameRej.identifier.text : "e"; const catchClause = createCatchClause(catchArg, createBlock(transformationBody2)); return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined) as Statement]; @@ -370,12 +370,11 @@ namespace ts.codefix { function transformPromiseCall(node: Expression, transformer: Transformer, prevArgName?: SynthIdentifier): Statement[] { const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(node).toString()); // the identifier is empty when the handler (.then()) ignores the argument - In this situation we do not need to save the result of the promise returning call - const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0; const originalNodeParent = node.original ? node.original.parent : node.parent; - if (hasPrevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { - return createTransformedStatement(prevArgName!, createAwait(node), transformer).concat(); // hack to make the types match + if (prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { + return createTransformedStatement(prevArgName, createAwait(node), transformer).concat(); // hack to make the types match } - else if (!hasPrevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { + else if (!prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { return [createStatement(createAwait(node))]; } @@ -398,18 +397,17 @@ namespace ts.codefix { } // should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts - function getTransformationBody(func: Node, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier, parent: CallExpression, transformer: Transformer): NodeArray { + function getTransformationBody(func: Node, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier | undefined, parent: CallExpression, transformer: Transformer): NodeArray { - const hasArgName = argName && argName.identifier.text.length > 0; const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString()); switch (func.kind) { case SyntaxKind.NullKeyword: // do not produce a transformed statement for a null argument break; case SyntaxKind.Identifier: // identifier includes undefined - if (!hasArgName) break; + if (!argName) break; - const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, [argName.identifier]); + const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, argName ? [argName.identifier] : []); if (shouldReturn) { return createNodeArray([createReturn(synthCall)]); } @@ -534,7 +532,7 @@ namespace ts.codefix { return innerCbBody; } - function getArgName(funcNode: Node, transformer: Transformer): SynthIdentifier { + function getArgName(funcNode: Node, transformer: Transformer): SynthIdentifier | undefined { const numberOfAssignmentsOriginal = 0; const types: Type[] = []; @@ -552,7 +550,7 @@ namespace ts.codefix { } if (!name || name.identifier === undefined || name.identifier.text === "undefined") { - return { identifier: createIdentifier(""), types, numberOfAssignmentsOriginal }; + return undefined; } return name; From 59e4770a512038f795680383f4854f7d1e79b375 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 17 Sep 2018 16:06:17 -0700 Subject: [PATCH 36/47] Fix enum tag circular references (#27161) * Fix enum tag circular references Also, don't try to resolve enum tag types in Typescript. * Improve comment --- src/compiler/checker.ts | 18 +++++++++++++++--- src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/types.ts | 1 + .../enumTagCircularReference.errors.txt | 9 +++++++++ .../reference/enumTagCircularReference.symbols | 6 ++++++ .../reference/enumTagCircularReference.types | 8 ++++++++ .../jsdoc/enumTagCircularReference.ts | 7 +++++++ 7 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/enumTagCircularReference.errors.txt create mode 100644 tests/baselines/reference/enumTagCircularReference.symbols create mode 100644 tests/baselines/reference/enumTagCircularReference.types create mode 100644 tests/cases/conformance/jsdoc/enumTagCircularReference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6d400b99e8a..8472be7b77c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -640,7 +640,7 @@ namespace ts { const identityRelation = createMap(); const enumRelation = createMap(); - type TypeSystemEntity = Symbol | Type | Signature; + type TypeSystemEntity = Node | Symbol | Type | Signature; const enum TypeSystemPropertyName { Type, @@ -648,6 +648,7 @@ namespace ts { DeclaredType, ResolvedReturnType, ImmediateBaseConstraint, + EnumTagType, } const enum CheckMode { @@ -4475,6 +4476,8 @@ namespace ts { switch (propertyName) { case TypeSystemPropertyName.Type: return !!getSymbolLinks(target).type; + case TypeSystemPropertyName.EnumTagType: + return !!(getNodeLinks(target as JSDocEnumTag).resolvedEnumType); case TypeSystemPropertyName.DeclaredType: return !!getSymbolLinks(target).declaredType; case TypeSystemPropertyName.ResolvedBaseConstructorType: @@ -8252,9 +8255,18 @@ namespace ts { } // JS are 'string' or 'number', not an enum type. - const enumTag = symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration); + const enumTag = isInJSFile(node) && symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration); if (enumTag) { - return enumTag.typeExpression ? getTypeFromTypeNode(enumTag.typeExpression) : errorType; + const links = getNodeLinks(enumTag); + if (!pushTypeResolution(enumTag, TypeSystemPropertyName.EnumTagType)) { + return errorType; + } + let type = enumTag.typeExpression ? getTypeFromTypeNode(enumTag.typeExpression) : errorType; + if (!popTypeResolution()) { + type = errorType; + error(node, Diagnostics.Enum_type_0_circularly_references_itself, symbolToString(symbol)); + } + return (links.resolvedEnumType = type); } // Get type from reference to named type that cannot be generic (enum or type parameter) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 42c594c19b0..d083c475bc2 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2112,6 +2112,10 @@ "category": "Error", "code": 2585 }, + "Enum type '{0}' circularly references itself.": { + "category": "Error", + "code": 2586 + }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 03a5d2b9ce7..df0396b172d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3676,6 +3676,7 @@ namespace ts { export interface NodeLinks { flags: NodeCheckFlags; // Set of flags specific to Node resolvedType?: Type; // Cached type of type node + resolvedEnumType?: Type; // Cached constraint type from enum jsdoc tag resolvedSignature?: Signature; // Cached signature of signature node or call expression resolvedSignatures?: Map; // Cached signatures of jsx node resolvedSymbol?: Symbol; // Cached name resolution result diff --git a/tests/baselines/reference/enumTagCircularReference.errors.txt b/tests/baselines/reference/enumTagCircularReference.errors.txt new file mode 100644 index 00000000000..f876b5a33da --- /dev/null +++ b/tests/baselines/reference/enumTagCircularReference.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/jsdoc/bug27142.js(1,12): error TS2586: Enum type 'E' circularly references itself. + + +==== tests/cases/conformance/jsdoc/bug27142.js (1 errors) ==== + /** @enum {E} */ + ~ +!!! error TS2586: Enum type 'E' circularly references itself. + const E = { x: 0 }; + \ No newline at end of file diff --git a/tests/baselines/reference/enumTagCircularReference.symbols b/tests/baselines/reference/enumTagCircularReference.symbols new file mode 100644 index 00000000000..e3c594ac9d1 --- /dev/null +++ b/tests/baselines/reference/enumTagCircularReference.symbols @@ -0,0 +1,6 @@ +=== tests/cases/conformance/jsdoc/bug27142.js === +/** @enum {E} */ +const E = { x: 0 }; +>E : Symbol(E, Decl(bug27142.js, 1, 5)) +>x : Symbol(x, Decl(bug27142.js, 1, 11)) + diff --git a/tests/baselines/reference/enumTagCircularReference.types b/tests/baselines/reference/enumTagCircularReference.types new file mode 100644 index 00000000000..32039379f5e --- /dev/null +++ b/tests/baselines/reference/enumTagCircularReference.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/jsdoc/bug27142.js === +/** @enum {E} */ +const E = { x: 0 }; +>E : { x: number; } +>{ x: 0 } : { x: number; } +>x : number +>0 : 0 + diff --git a/tests/cases/conformance/jsdoc/enumTagCircularReference.ts b/tests/cases/conformance/jsdoc/enumTagCircularReference.ts new file mode 100644 index 00000000000..c4015b70985 --- /dev/null +++ b/tests/cases/conformance/jsdoc/enumTagCircularReference.ts @@ -0,0 +1,7 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: bug27142.js + +/** @enum {E} */ +const E = { x: 0 }; From a73b561dd3b4e7eae48fbf8e30b4aec5022424e3 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 16:23:47 -0700 Subject: [PATCH 37/47] Ensure name for callback is generated even when it has no args --- src/services/codefixes/convertToAsyncFunction.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index b9b5fe150d5..5625f5b4a55 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -172,9 +172,9 @@ namespace ts.codefix { // if the identifier refers to a function we want to add the new synthesized variable for the declaration (ex. blob in let blob = res(arg)) // Note - the choice of the last call signature is arbitrary - if (lastCallSignature && lastCallSignature.parameters.length && !synthNamesMap.has(symbolIdString)) { - const firstParameter = lastCallSignature.parameters[0]; - const ident = isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result"); + if (lastCallSignature && !synthNamesMap.has(symbolIdString)) { + const firstParameter = firstOrUndefined(lastCallSignature.parameters); + const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result"); const synthName = getNewNameIfConflict(ident, collidingSymbolMap); synthNamesMap.set(symbolIdString, synthName); allVarNames.push({ identifier: synthName.identifier, symbol }); From 76b0b2f1e8fc12757939fe14800317f317a5acba Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 16:23:52 -0700 Subject: [PATCH 38/47] Add test --- .../unittests/convertToAsyncFunction.ts | 9 +++++++++ .../convertToAsyncFunction_IgnoreArgs4.js | 17 +++++++++++++++++ .../convertToAsyncFunction_IgnoreArgs4.ts | 17 +++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.ts diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index d7e70e4d1e5..5eb49eaa445 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -421,6 +421,15 @@ function [#|f|](): Promise { return fetch('https://typescriptlang.org').then( () => console.log("almost done") ).then( () => console.log("done") ); }` ); + _testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs4", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(res); +} +function res(){ + console.log("done"); +}` + ); + _testConvertToAsyncFunction("convertToAsyncFunction_Method", ` class Parser { [#|f|]():Promise { diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.js new file mode 100644 index 00000000000..a03eb467b2f --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.js @@ -0,0 +1,17 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(res); +} +function res(){ + console.log("done"); +} +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const result_1 = await fetch('https://typescriptlang.org'); + return res(result_1); +} +function res(){ + console.log("done"); +} \ No newline at end of file diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.ts new file mode 100644 index 00000000000..a03eb467b2f --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.ts @@ -0,0 +1,17 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(res); +} +function res(){ + console.log("done"); +} +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const result_1 = await fetch('https://typescriptlang.org'); + return res(result_1); +} +function res(){ + console.log("done"); +} \ No newline at end of file From b2378ca40ca4aa29c9dd08d4dc1b1a53e45f7f64 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 17 Sep 2018 16:33:32 -0700 Subject: [PATCH 39/47] Stop adding name of function being fixed and update baseline --- src/services/codefixes/convertToAsyncFunction.ts | 2 +- .../convertToAsyncFunction_IgnoreArgs4.js | 4 ++-- .../convertToAsyncFunction_IgnoreArgs4.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 5625f5b4a55..a972dff548a 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -172,7 +172,7 @@ namespace ts.codefix { // if the identifier refers to a function we want to add the new synthesized variable for the declaration (ex. blob in let blob = res(arg)) // Note - the choice of the last call signature is arbitrary - if (lastCallSignature && !synthNamesMap.has(symbolIdString)) { + if (lastCallSignature && !isFunctionLikeDeclaration(node.parent) && !synthNamesMap.has(symbolIdString)) { const firstParameter = firstOrUndefined(lastCallSignature.parameters); const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result"); const synthName = getNewNameIfConflict(ident, collidingSymbolMap); diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.js index a03eb467b2f..a8cbdff4451 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.js +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.js @@ -9,8 +9,8 @@ function res(){ // ==ASYNC FUNCTION::Convert to async function== async function f() { - const result_1 = await fetch('https://typescriptlang.org'); - return res(result_1); + const result = await fetch('https://typescriptlang.org'); + return res(result); } function res(){ console.log("done"); diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.ts index a03eb467b2f..a8cbdff4451 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_IgnoreArgs4.ts @@ -9,8 +9,8 @@ function res(){ // ==ASYNC FUNCTION::Convert to async function== async function f() { - const result_1 = await fetch('https://typescriptlang.org'); - return res(result_1); + const result = await fetch('https://typescriptlang.org'); + return res(result); } function res(){ console.log("done"); From f6321bf6d5bcb020e17ec7be7dcfc8c5d30da22c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 17 Sep 2018 16:45:54 -0700 Subject: [PATCH 40/47] Elaborate into arrow return expressions and array types (#27040) * Dive into simple arrow functions when elaborating errors * Dive into array literals as though they were tuples when elaborating, if possible * Make parameter required * Remove misleading errors by deeply tuplefying * Remove lib related spans --- src/compiler/checker.ts | 87 +++++++++++++++---- src/compiler/diagnosticMessages.json | 4 + .../arrayLiteralTypeInference.errors.txt | 36 ++++---- .../reference/arrayLiterals.errors.txt | 23 ++--- .../reference/arraySigChecking.errors.txt | 23 +++-- .../reference/assignmentCompatBug5.errors.txt | 13 +-- .../assignmentToObjectAndFunction.errors.txt | 1 - ...ConstrainedToOtherTypeParameter.errors.txt | 13 ++- ...onstrainedToOtherTypeParameter2.errors.txt | 18 ++-- .../reference/contextualTyping11.errors.txt | 12 ++- .../reference/contextualTyping12.errors.txt | 12 +-- .../reference/contextualTyping20.errors.txt | 12 +-- .../reference/contextualTyping21.errors.txt | 10 +-- .../reference/contextualTyping30.errors.txt | 10 +-- .../reference/contextualTyping33.errors.txt | 14 ++- .../reference/contextualTyping9.errors.txt | 12 +-- ...ontextualTypingOfArrayLiterals1.errors.txt | 13 +-- ...TypedBindingInitializerNegative.errors.txt | 46 +++++----- ...laborationsIntoArrowExpressions.errors.txt | 37 ++++++++ .../deepElaborationsIntoArrowExpressions.js | 31 +++++++ ...epElaborationsIntoArrowExpressions.symbols | 40 +++++++++ ...deepElaborationsIntoArrowExpressions.types | 49 +++++++++++ ...tructuringParameterDeclaration4.errors.txt | 10 +-- ...structuringVariableDeclaration2.errors.txt | 8 +- ...AnnotationAndInvalidInitializer.errors.txt | 9 +- ...fixingTypeParametersRepeatedly2.errors.txt | 13 ++- tests/baselines/reference/for-of10.errors.txt | 4 +- tests/baselines/reference/for-of11.errors.txt | 8 +- tests/baselines/reference/for-of39.errors.txt | 12 +-- .../reference/functionOverloads40.errors.txt | 13 +-- .../reference/functionOverloads41.errors.txt | 12 ++- ...lWithGenericSignatureArguments2.errors.txt | 9 +- .../heterogeneousArrayAndOverloads.errors.txt | 18 ++-- .../iterableArrayPattern28.errors.txt | 12 +-- .../iteratorSpreadInArray5.errors.txt | 10 +-- ...xChildrenGenericContextualTypes.errors.txt | 10 +-- .../keyofIsLiteralContexualType.errors.txt | 14 ++- ...citTypeParameterAndArgumentType.errors.txt | 10 +-- ...ralFunctionArgContextualTyping2.errors.txt | 5 +- ...LiteralsAgainstUnionsOfArrays01.errors.txt | 25 +++--- .../overloadResolutionOverCTLambda.errors.txt | 9 +- .../overloadResolutionTest1.errors.txt | 13 +-- .../overloadsWithProvisionalErrors.errors.txt | 26 +++--- .../reference/promiseChaining1.errors.txt | 9 +- .../reference/promiseChaining2.errors.txt | 9 +- .../reference/promiseTypeInference.errors.txt | 33 ++++--- .../reference/targetTypeTest3.errors.txt | 15 ++-- ...ommaInHeterogenousArrayLiteral1.errors.txt | 16 ++-- ...entPartialDefinitionStillErrors.errors.txt | 1 - ...rgumentInferenceWithConstraints.errors.txt | 9 +- ...gWithContextSensitiveArguments2.errors.txt | 13 ++- ...gWithContextSensitiveArguments3.errors.txt | 13 ++- .../reference/widenedTypes.errors.txt | 8 +- ...wrappedAndRecursiveConstraints4.errors.txt | 3 +- .../deepElaborationsIntoArrowExpressions.ts | 19 ++++ 55 files changed, 517 insertions(+), 397 deletions(-) create mode 100644 tests/baselines/reference/deepElaborationsIntoArrowExpressions.errors.txt create mode 100644 tests/baselines/reference/deepElaborationsIntoArrowExpressions.js create mode 100644 tests/baselines/reference/deepElaborationsIntoArrowExpressions.symbols create mode 100644 tests/baselines/reference/deepElaborationsIntoArrowExpressions.types create mode 100644 tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f2b01c6fd56..f4fc99406e0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10636,6 +10636,8 @@ namespace ts { return elaborateArrayLiteral(node as ArrayLiteralExpression, source, target, relation); case SyntaxKind.JsxAttributes: return elaborateJsxAttributes(node as JsxAttributes, source, target, relation); + case SyntaxKind.ArrowFunction: + return elaborateArrowFunction(node as ArrowFunction, source, target, relation); } return false; } @@ -10661,6 +10663,46 @@ namespace ts { return false; } + function elaborateArrowFunction(node: ArrowFunction, source: Type, target: Type, relation: Map): boolean { + // Don't elaborate blocks + if (isBlock(node.body)) { + return false; + } + // Or functions with annotated parameter types + if (some(node.parameters, ts.hasType)) { + return false; + } + const sourceSig = getSingleCallSignature(source); + if (!sourceSig) { + return false; + } + const targetSignatures = getSignaturesOfType(target, SignatureKind.Call); + if (!length(targetSignatures)) { + return false; + } + const returnExpression = node.body; + const sourceReturn = getReturnTypeOfSignature(sourceSig); + const targetReturn = getUnionType(map(targetSignatures, getReturnTypeOfSignature)); + if (!checkTypeRelatedTo(sourceReturn, targetReturn, relation, /*errorNode*/ undefined)) { + const elaborated = returnExpression && elaborateError(returnExpression, sourceReturn, targetReturn, relation, /*headMessage*/ undefined); + if (elaborated) { + return elaborated; + } + const resultObj: { error?: Diagnostic } = {}; + checkTypeRelatedTo(sourceReturn, targetReturn, relation, returnExpression, /*message*/ undefined, /*chain*/ undefined, resultObj); + if (resultObj.error) { + if (target.symbol && length(target.symbol.declarations)) { + addRelatedInfo(resultObj.error, createDiagnosticForNode( + target.symbol.declarations[0], + Diagnostics.The_expected_type_comes_from_the_return_type_of_this_signature, + )); + } + return true; + } + } + return false; + } + type ElaborationIterator = IterableIterator<{ errorNode: Node, innerExpression: Expression | undefined, nameType: Type, errorMessage?: DiagnosticMessage | undefined }>; /** * For every element returned from the iterator, checks that element to issue an error on a property of that element's type @@ -10674,7 +10716,7 @@ namespace ts { const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value; const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType); const targetPropType = getIndexedAccessType(target, nameType, /*accessNode*/ undefined, errorType); - if (sourcePropType !== errorType && targetPropType !== errorType && !isTypeAssignableTo(sourcePropType, targetPropType)) { + if (sourcePropType !== errorType && targetPropType !== errorType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) { const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined); if (elaborated) { reportedError = true; @@ -10699,19 +10741,22 @@ namespace ts { const indexInfo = isTypeAssignableToKind(nameType, TypeFlags.NumberLike) && getIndexInfoOfType(target, IndexKind.Number) || getIndexInfoOfType(target, IndexKind.String) || undefined; - if (indexInfo && indexInfo.declaration) { + if (indexInfo && indexInfo.declaration && !getSourceFileOfNode(indexInfo.declaration).hasNoDefaultLib) { issuedElaboration = true; addRelatedInfo(reportedDiag, createDiagnosticForNode(indexInfo.declaration, Diagnostics.The_expected_type_comes_from_this_index_signature)); } } if (!issuedElaboration && (targetProp && length(targetProp.declarations) || target.symbol && length(target.symbol.declarations))) { - addRelatedInfo(reportedDiag, createDiagnosticForNode( - targetProp && length(targetProp.declarations) ? targetProp.declarations[0] : target.symbol.declarations[0], - Diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1, - propertyName && !(nameType.flags & TypeFlags.UniqueESSymbol) ? unescapeLeadingUnderscores(propertyName) : typeToString(nameType), - typeToString(target) - )); + const targetNode = targetProp && length(targetProp.declarations) ? targetProp.declarations[0] : target.symbol.declarations[0]; + if (!getSourceFileOfNode(targetNode).hasNoDefaultLib) { + addRelatedInfo(reportedDiag, createDiagnosticForNode( + targetNode, + Diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1, + propertyName && !(nameType.flags & TypeFlags.UniqueESSymbol) ? unescapeLeadingUnderscores(propertyName) : typeToString(nameType), + typeToString(target) + )); + } } } reportedError = true; @@ -10750,6 +10795,11 @@ namespace ts { if (isTupleLikeType(source)) { return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation); } + // recreate a tuple from the elements, if possible + const tupleizedType = checkArrayLiteral(node, CheckMode.Contextual, /*forceTuple*/ true); + if (isTupleLikeType(tupleizedType)) { + return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation); + } return false; } @@ -16981,7 +17031,7 @@ namespace ts { (node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.EqualsToken); } - function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined): Type { + function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined, forceTuple: boolean | undefined): Type { const elements = node.elements; const elementCount = elements.length; let hasNonEndingSpreadElement = false; @@ -17003,7 +17053,7 @@ namespace ts { // get the contextual element type from it. So we do something similar to // getContextualTypeForElementExpression, which will crucially not error // if there is no index type / iterated type. - const restArrayType = checkExpression((e).expression, checkMode); + const restArrayType = checkExpression((e).expression, checkMode, forceTuple); const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) || getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false); if (restElementType) { @@ -17012,7 +17062,7 @@ namespace ts { } else { const elementContextualType = getContextualTypeForElementExpression(contextualType, index); - const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType); + const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple); elementTypes.push(type); } if (index < elementCount - 1 && e.kind === SyntaxKind.SpreadElement) { @@ -17050,6 +17100,9 @@ namespace ts { } return createTupleType(elementTypes, minLength, hasRestElement); } + else if (forceTuple) { + return createTupleType(elementTypes, minLength, hasRestElement); + } } return getArrayLiteralType(elementTypes, UnionReduction.Subtype); } @@ -22097,11 +22150,11 @@ namespace ts { return false; } - function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type): Type { + function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type, forceTuple?: boolean): Type { if (arguments.length === 2) { contextualType = getContextualType(node); } - const type = checkExpression(node, checkMode); + const type = checkExpression(node, checkMode, forceTuple); return isTypeAssertion(node) ? type : getWidenedLiteralLikeTypeForContextualType(type, contextualType); } @@ -22201,13 +22254,13 @@ namespace ts { // object, it serves as an indicator that all contained function and arrow expressions should be considered to // have the wildcard function type; this form of type check is used during overload resolution to exclude // contextually typed function and arrow expressions in the initial phase. - function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode): Type { + function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type { let type: Type; if (node.kind === SyntaxKind.QualifiedName) { type = checkQualifiedName(node); } else { - const uninstantiatedType = checkExpressionWorker(node, checkMode); + const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple); type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } @@ -22237,7 +22290,7 @@ namespace ts { return checkExpression(node.expression, checkMode); } - function checkExpressionWorker(node: Expression, checkMode: CheckMode | undefined): Type { + function checkExpressionWorker(node: Expression, checkMode: CheckMode | undefined, forceTuple?: boolean): Type { switch (node.kind) { case SyntaxKind.Identifier: return checkIdentifier(node); @@ -22262,7 +22315,7 @@ namespace ts { case SyntaxKind.RegularExpressionLiteral: return globalRegExpType; case SyntaxKind.ArrayLiteralExpression: - return checkArrayLiteral(node, checkMode); + return checkArrayLiteral(node, checkMode, forceTuple); case SyntaxKind.ObjectLiteralExpression: return checkObjectLiteral(node, checkMode); case SyntaxKind.PropertyAccessExpression: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index d083c475bc2..eb83d48ae75 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3890,6 +3890,10 @@ "category": "Message", "code": 6501 }, + "The expected type comes from the return type of this signature.": { + "category": "Message", + "code": 6502 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/tests/baselines/reference/arrayLiteralTypeInference.errors.txt b/tests/baselines/reference/arrayLiteralTypeInference.errors.txt index a2c4597127f..efffc256a83 100644 --- a/tests/baselines/reference/arrayLiteralTypeInference.errors.txt +++ b/tests/baselines/reference/arrayLiteralTypeInference.errors.txt @@ -1,14 +1,14 @@ -tests/cases/compiler/arrayLiteralTypeInference.ts(14,14): error TS2322: Type '({ id: number; trueness: boolean; } | { id: number; name: string; })[]' is not assignable to type 'Action[]'. - Type '{ id: number; trueness: boolean; } | { id: number; name: string; }' is not assignable to type 'Action'. - Type '{ id: number; trueness: boolean; }' is not assignable to type 'Action'. - Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'. -tests/cases/compiler/arrayLiteralTypeInference.ts(31,18): error TS2322: Type '({ id: number; trueness: boolean; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'. - Type '{ id: number; trueness: boolean; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'. - Type '{ id: number; trueness: boolean; }' is not assignable to type '{ id: number; }'. - Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'. +tests/cases/compiler/arrayLiteralTypeInference.ts(14,14): error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type 'Action'. + Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'. +tests/cases/compiler/arrayLiteralTypeInference.ts(15,14): error TS2322: Type '{ id: number; name: string; }' is not assignable to type 'Action'. + Object literal may only specify known properties, and 'name' does not exist in type 'Action'. +tests/cases/compiler/arrayLiteralTypeInference.ts(31,18): error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type '{ id: number; }'. + Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'. +tests/cases/compiler/arrayLiteralTypeInference.ts(32,18): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. + Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. -==== tests/cases/compiler/arrayLiteralTypeInference.ts (2 errors) ==== +==== tests/cases/compiler/arrayLiteralTypeInference.ts (4 errors) ==== class Action { id: number; } @@ -24,11 +24,12 @@ tests/cases/compiler/arrayLiteralTypeInference.ts(31,18): error TS2322: Type '({ var x1: Action[] = [ { id: 2, trueness: false }, ~~~~~~~~~~~~~~~ -!!! error TS2322: Type '({ id: number; trueness: boolean; } | { id: number; name: string; })[]' is not assignable to type 'Action[]'. -!!! error TS2322: Type '{ id: number; trueness: boolean; } | { id: number; name: string; }' is not assignable to type 'Action'. -!!! error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type 'Action'. -!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'. +!!! error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type 'Action'. +!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'. { id: 3, name: "three" } + ~~~~~~~~~~~~~ +!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type 'Action'. +!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type 'Action'. ] var x2: Action[] = [ @@ -46,11 +47,12 @@ tests/cases/compiler/arrayLiteralTypeInference.ts(31,18): error TS2322: Type '({ [ { id: 2, trueness: false }, ~~~~~~~~~~~~~~~ -!!! error TS2322: Type '({ id: number; trueness: boolean; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'. -!!! error TS2322: Type '{ id: number; trueness: boolean; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'. +!!! error TS2322: Type '{ id: number; trueness: boolean; }' is not assignable to type '{ id: number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'. { id: 3, name: "three" } + ~~~~~~~~~~~~~ +!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. ] var z2: { id: number }[] = diff --git a/tests/baselines/reference/arrayLiterals.errors.txt b/tests/baselines/reference/arrayLiterals.errors.txt index f5fe71b79a6..4b9ca295f95 100644 --- a/tests/baselines/reference/arrayLiterals.errors.txt +++ b/tests/baselines/reference/arrayLiterals.errors.txt @@ -1,11 +1,10 @@ -tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts(24,77): error TS2322: Type '({ a: string; b: number; c: string; } | { a: string; b: number; c: number; })[]' is not assignable to type '{ [n: number]: { a: string; b: number; }; }'. - Index signatures are incompatible. - Type '{ a: string; b: number; c: string; } | { a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'. - Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'. - Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'. +tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts(24,77): error TS2322: Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'. + Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'. +tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts(24,101): error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'. + Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'. -==== tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts (1 errors) ==== +==== tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts (2 errors) ==== // Empty array literal with no contextual type has type Undefined[] var arr1= [[], [1], ['']]; @@ -31,11 +30,13 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts(24,77): error // Contextual type C with numeric index signature makes array literal of EveryType E of type BCT(E,C)[] var context1: { [n: number]: { a: string; b: number; }; } = [{ a: '', b: 0, c: '' }, { a: "", b: 3, c: 0 }]; ~~~~~ -!!! error TS2322: Type '({ a: string; b: number; c: string; } | { a: string; b: number; c: number; })[]' is not assignable to type '{ [n: number]: { a: string; b: number; }; }'. -!!! error TS2322: Index signatures are incompatible. -!!! error TS2322: Type '{ a: string; b: number; c: string; } | { a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'. -!!! error TS2322: Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'. -!!! error TS2322: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'. +!!! error TS2322: Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'. +!!! related TS6501 tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts:24:17: The expected type comes from this index signature. + ~~~~ +!!! error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'. +!!! related TS6501 tests/cases/conformance/expressions/arrayLiterals/arrayLiterals.ts:24:17: The expected type comes from this index signature. var context2 = [{ a: '', b: 0, c: '' }, { a: "", b: 3, c: 0 }]; // Contextual type C with numeric index signature of type Base makes array literal of Derived have type Base[] diff --git a/tests/baselines/reference/arraySigChecking.errors.txt b/tests/baselines/reference/arraySigChecking.errors.txt index 1968957363c..a1f219919d8 100644 --- a/tests/baselines/reference/arraySigChecking.errors.txt +++ b/tests/baselines/reference/arraySigChecking.errors.txt @@ -1,12 +1,10 @@ tests/cases/compiler/arraySigChecking.ts(11,17): error TS1023: An index signature parameter type must be 'string' or 'number'. -tests/cases/compiler/arraySigChecking.ts(18,5): error TS2322: Type 'void[]' is not assignable to type 'string[]'. - Type 'void' is not assignable to type 'string'. -tests/cases/compiler/arraySigChecking.ts(22,1): error TS2322: Type 'number[][]' is not assignable to type 'number[][][]'. - Type 'number[]' is not assignable to type 'number[][]'. - Type 'number' is not assignable to type 'number[]'. +tests/cases/compiler/arraySigChecking.ts(18,27): error TS2322: Type 'void' is not assignable to type 'string'. +tests/cases/compiler/arraySigChecking.ts(22,13): error TS2322: Type 'number' is not assignable to type 'number[]'. +tests/cases/compiler/arraySigChecking.ts(22,16): error TS2322: Type 'number' is not assignable to type 'number[]'. -==== tests/cases/compiler/arraySigChecking.ts (3 errors) ==== +==== tests/cases/compiler/arraySigChecking.ts (4 errors) ==== declare module M { interface iBar { t: any; } interface iFoo extends iBar { @@ -27,17 +25,16 @@ tests/cases/compiler/arraySigChecking.ts(22,1): error TS2322: Type 'number[][]' } var myVar: myInt; var strArray: string[] = [myVar.voidFn()]; - ~~~~~~~~ -!!! error TS2322: Type 'void[]' is not assignable to type 'string[]'. -!!! error TS2322: Type 'void' is not assignable to type 'string'. + ~~~~~~~~~~~~~~ +!!! error TS2322: Type 'void' is not assignable to type 'string'. var myArray: number[][][]; myArray = [[1, 2]]; - ~~~~~~~ -!!! error TS2322: Type 'number[][]' is not assignable to type 'number[][][]'. -!!! error TS2322: Type 'number[]' is not assignable to type 'number[][]'. -!!! error TS2322: Type 'number' is not assignable to type 'number[]'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'number[]'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'number[]'. function isEmpty(l: { length: number }) { return l.length === 0; diff --git a/tests/baselines/reference/assignmentCompatBug5.errors.txt b/tests/baselines/reference/assignmentCompatBug5.errors.txt index 44e28f15d8c..6a5c5569c8f 100644 --- a/tests/baselines/reference/assignmentCompatBug5.errors.txt +++ b/tests/baselines/reference/assignmentCompatBug5.errors.txt @@ -1,7 +1,7 @@ tests/cases/compiler/assignmentCompatBug5.ts(2,8): error TS2345: Argument of type '{ b: number; }' is not assignable to parameter of type '{ a: number; }'. Object literal may only specify known properties, and 'b' does not exist in type '{ a: number; }'. -tests/cases/compiler/assignmentCompatBug5.ts(5,6): error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'number[]'. - Type 'string' is not assignable to type 'number'. +tests/cases/compiler/assignmentCompatBug5.ts(5,7): error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/assignmentCompatBug5.ts(5,12): error TS2322: Type 'string' is not assignable to type 'number'. tests/cases/compiler/assignmentCompatBug5.ts(8,6): error TS2345: Argument of type '(s: string) => void' is not assignable to parameter of type '(n: number) => number'. Types of parameters 's' and 'n' are incompatible. Type 'number' is not assignable to type 'string'. @@ -9,7 +9,7 @@ tests/cases/compiler/assignmentCompatBug5.ts(9,6): error TS2345: Argument of typ Type 'void' is not assignable to type 'number'. -==== tests/cases/compiler/assignmentCompatBug5.ts (4 errors) ==== +==== tests/cases/compiler/assignmentCompatBug5.ts (5 errors) ==== function foo1(x: { a: number; }) { } foo1({ b: 5 }); ~~~~ @@ -18,9 +18,10 @@ tests/cases/compiler/assignmentCompatBug5.ts(9,6): error TS2345: Argument of typ function foo2(x: number[]) { } foo2(["s", "t"]); - ~~~~~~~~~~ -!!! error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'number[]'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. function foo3(x: (n: number) =>number) { }; foo3((s:string) => { }); diff --git a/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt b/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt index 8ba04d8ab2c..9e28f5e9177 100644 --- a/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt +++ b/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt @@ -10,7 +10,6 @@ tests/cases/compiler/assignmentToObjectAndFunction.ts(29,5): error TS2322: Type var errObj: Object = { toString: 0 }; // Error, incompatible toString ~~~~~~~~ !!! error TS2322: Type 'number' is not assignable to type '() => string'. -!!! related TS6500 /.ts/lib.es5.d.ts:125:5: The expected type comes from property 'toString' which is declared here on type 'Object' var goodObj: Object = { toString(x?) { return ""; diff --git a/tests/baselines/reference/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.errors.txt b/tests/baselines/reference/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.errors.txt index 181bfcc907d..cee9236d630 100644 --- a/tests/baselines/reference/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.errors.txt +++ b/tests/baselines/reference/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.errors.txt @@ -1,6 +1,5 @@ -tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,59): error TS2345: Argument of type '(c: C) => B' is not assignable to parameter of type '(x: C) => C'. - Type 'B' is not assignable to type 'C'. - Property 'z' is missing in type 'B'. +tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,64): error TS2322: Type 'B' is not assignable to type 'C'. + Property 'z' is missing in type 'B'. ==== tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts (1 errors) ==== @@ -23,7 +22,7 @@ tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParamete // Ok to go down the chain, but error to try to climb back up (new Chain(new A)).then(a => new B).then(b => new C).then(c => new B).then(b => new A); - ~~~~~~~~~~ -!!! error TS2345: Argument of type '(c: C) => B' is not assignable to parameter of type '(x: C) => C'. -!!! error TS2345: Type 'B' is not assignable to type 'C'. -!!! error TS2345: Property 'z' is missing in type 'B'. \ No newline at end of file + ~~~~~ +!!! error TS2322: Type 'B' is not assignable to type 'C'. +!!! error TS2322: Property 'z' is missing in type 'B'. +!!! related TS6502 tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts:3:27: The expected type comes from the return type of this signature. \ No newline at end of file diff --git a/tests/baselines/reference/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.errors.txt b/tests/baselines/reference/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.errors.txt index 56f4cad5a47..6f03e711886 100644 --- a/tests/baselines/reference/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.errors.txt +++ b/tests/baselines/reference/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.errors.txt @@ -1,7 +1,5 @@ -tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(7,43): error TS2345: Argument of type '(ss: S) => T' is not assignable to parameter of type '(x: S) => S'. - Type 'T' is not assignable to type 'S'. -tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(10,29): error TS2345: Argument of type '(ss: S) => T' is not assignable to parameter of type '(x: S) => S'. - Type 'T' is not assignable to type 'S'. +tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(7,49): error TS2322: Type 'T' is not assignable to type 'S'. +tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(10,35): error TS2322: Type 'T' is not assignable to type 'S'. tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(32,9): error TS2322: Type '""' is not assignable to type 'number'. tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(36,9): error TS2322: Type '""' is not assignable to type 'number'. tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts(37,9): error TS2322: Type '""' is not assignable to type 'number'. @@ -15,15 +13,15 @@ tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParamete var s: S; // Ok to go down the chain, but error to climb up the chain (new Chain(t)).then(tt => s).then(ss => t); - ~~~~~~~ -!!! error TS2345: Argument of type '(ss: S) => T' is not assignable to parameter of type '(x: S) => S'. -!!! error TS2345: Type 'T' is not assignable to type 'S'. + ~ +!!! error TS2322: Type 'T' is not assignable to type 'S'. +!!! related TS6502 tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts:3:27: The expected type comes from the return type of this signature. // But error to try to climb up the chain (new Chain(s)).then(ss => t); - ~~~~~~~ -!!! error TS2345: Argument of type '(ss: S) => T' is not assignable to parameter of type '(x: S) => S'. -!!! error TS2345: Type 'T' is not assignable to type 'S'. + ~ +!!! error TS2322: Type 'T' is not assignable to type 'S'. +!!! related TS6502 tests/cases/compiler/chainedCallsWithTypeParameterConstrainedToOtherTypeParameter2.ts:3:27: The expected type comes from the return type of this signature. // Staying at T or S should be fine (new Chain(t)).then(tt => t).then(tt => t).then(tt => t); diff --git a/tests/baselines/reference/contextualTyping11.errors.txt b/tests/baselines/reference/contextualTyping11.errors.txt index 0b7cf231c12..3aadb41cc0d 100644 --- a/tests/baselines/reference/contextualTyping11.errors.txt +++ b/tests/baselines/reference/contextualTyping11.errors.txt @@ -1,11 +1,9 @@ -tests/cases/compiler/contextualTyping11.ts(1,20): error TS2322: Type 'foo[]' is not assignable to type '{ id: number; }[]'. - Type 'foo' is not assignable to type '{ id: number; }'. - Property 'id' is missing in type 'foo'. +tests/cases/compiler/contextualTyping11.ts(1,42): error TS2322: Type 'foo' is not assignable to type '{ id: number; }'. + Property 'id' is missing in type 'foo'. ==== tests/cases/compiler/contextualTyping11.ts (1 errors) ==== class foo { public bar:{id:number;}[] = [({})]; } - ~~~ -!!! error TS2322: Type 'foo[]' is not assignable to type '{ id: number; }[]'. -!!! error TS2322: Type 'foo' is not assignable to type '{ id: number; }'. -!!! error TS2322: Property 'id' is missing in type 'foo'. \ No newline at end of file + ~~~~~~~~~ +!!! error TS2322: Type 'foo' is not assignable to type '{ id: number; }'. +!!! error TS2322: Property 'id' is missing in type 'foo'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping12.errors.txt b/tests/baselines/reference/contextualTyping12.errors.txt index 22ed6ad931e..3a2225b6817 100644 --- a/tests/baselines/reference/contextualTyping12.errors.txt +++ b/tests/baselines/reference/contextualTyping12.errors.txt @@ -1,13 +1,9 @@ -tests/cases/compiler/contextualTyping12.ts(1,57): error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'. - Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'. - Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. - Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. +tests/cases/compiler/contextualTyping12.ts(1,57): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. + Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. ==== tests/cases/compiler/contextualTyping12.ts (1 errors) ==== class foo { public bar:{id:number;}[] = [{id:1}, {id:2, name:"foo"}]; } ~~~~~~~~~~ -!!! error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'. -!!! error TS2322: Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. \ No newline at end of file +!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping20.errors.txt b/tests/baselines/reference/contextualTyping20.errors.txt index a9112f1db84..968fb8f2dc1 100644 --- a/tests/baselines/reference/contextualTyping20.errors.txt +++ b/tests/baselines/reference/contextualTyping20.errors.txt @@ -1,13 +1,9 @@ -tests/cases/compiler/contextualTyping20.ts(1,58): error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'. - Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'. - Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. - Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. +tests/cases/compiler/contextualTyping20.ts(1,58): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. + Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. ==== tests/cases/compiler/contextualTyping20.ts (1 errors) ==== var foo:{id:number;}[] = [{id:1}]; foo = [{id:1}, {id:2, name:"foo"}]; ~~~~~~~~~~ -!!! error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'. -!!! error TS2322: Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. \ No newline at end of file +!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping21.errors.txt b/tests/baselines/reference/contextualTyping21.errors.txt index 0bac30d5b44..85fbf26236c 100644 --- a/tests/baselines/reference/contextualTyping21.errors.txt +++ b/tests/baselines/reference/contextualTyping21.errors.txt @@ -1,11 +1,7 @@ -tests/cases/compiler/contextualTyping21.ts(1,36): error TS2322: Type '(number | { id: number; })[]' is not assignable to type '{ id: number; }[]'. - Type 'number | { id: number; }' is not assignable to type '{ id: number; }'. - Type 'number' is not assignable to type '{ id: number; }'. +tests/cases/compiler/contextualTyping21.ts(1,51): error TS2322: Type 'number' is not assignable to type '{ id: number; }'. ==== tests/cases/compiler/contextualTyping21.ts (1 errors) ==== var foo:{id:number;}[] = [{id:1}]; foo = [{id:1}, 1]; - ~~~ -!!! error TS2322: Type '(number | { id: number; })[]' is not assignable to type '{ id: number; }[]'. -!!! error TS2322: Type 'number | { id: number; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Type 'number' is not assignable to type '{ id: number; }'. \ No newline at end of file + ~ +!!! error TS2322: Type 'number' is not assignable to type '{ id: number; }'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping30.errors.txt b/tests/baselines/reference/contextualTyping30.errors.txt index eda30769ac8..43aebc4cd9a 100644 --- a/tests/baselines/reference/contextualTyping30.errors.txt +++ b/tests/baselines/reference/contextualTyping30.errors.txt @@ -1,11 +1,7 @@ -tests/cases/compiler/contextualTyping30.ts(1,37): error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. +tests/cases/compiler/contextualTyping30.ts(1,41): error TS2322: Type 'string' is not assignable to type 'number'. ==== tests/cases/compiler/contextualTyping30.ts (1 errors) ==== function foo(param:number[]){}; foo([1, "a"]); - ~~~~~~~~ -!!! error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. -!!! error TS2345: Type 'string | number' is not assignable to type 'number'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. \ No newline at end of file + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping33.errors.txt b/tests/baselines/reference/contextualTyping33.errors.txt index 16c975391a3..8dc9b41fabf 100644 --- a/tests/baselines/reference/contextualTyping33.errors.txt +++ b/tests/baselines/reference/contextualTyping33.errors.txt @@ -1,13 +1,9 @@ -tests/cases/compiler/contextualTyping33.ts(1,66): error TS2345: Argument of type '((() => number) | (() => string))[]' is not assignable to parameter of type '{ (): number; (i: number): number; }[]'. - Type '(() => number) | (() => string)' is not assignable to type '{ (): number; (i: number): number; }'. - Type '() => string' is not assignable to type '{ (): number; (i: number): number; }'. - Type 'string' is not assignable to type 'number'. +tests/cases/compiler/contextualTyping33.ts(1,90): error TS2322: Type '() => string' is not assignable to type '{ (): number; (i: number): number; }'. + Type 'string' is not assignable to type 'number'. ==== tests/cases/compiler/contextualTyping33.ts (1 errors) ==== function foo(param: {():number; (i:number):number; }[]) { }; foo([function(){return 1;}, function(){return "foo"}]); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '((() => number) | (() => string))[]' is not assignable to parameter of type '{ (): number; (i: number): number; }[]'. -!!! error TS2345: Type '(() => number) | (() => string)' is not assignable to type '{ (): number; (i: number): number; }'. -!!! error TS2345: Type '() => string' is not assignable to type '{ (): number; (i: number): number; }'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. \ No newline at end of file + ~~~~~~~~ +!!! error TS2322: Type '() => string' is not assignable to type '{ (): number; (i: number): number; }'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping9.errors.txt b/tests/baselines/reference/contextualTyping9.errors.txt index 4a12574fa21..05b7df1d065 100644 --- a/tests/baselines/reference/contextualTyping9.errors.txt +++ b/tests/baselines/reference/contextualTyping9.errors.txt @@ -1,13 +1,9 @@ -tests/cases/compiler/contextualTyping9.ts(1,42): error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'. - Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'. - Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. - Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. +tests/cases/compiler/contextualTyping9.ts(1,42): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. + Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. ==== tests/cases/compiler/contextualTyping9.ts (1 errors) ==== var foo:{id:number;}[] = [{id:1}, {id:2, name:"foo"}]; ~~~~~~~~~~ -!!! error TS2322: Type '({ id: number; } | { id: number; name: string; })[]' is not assignable to type '{ id: number; }[]'. -!!! error TS2322: Type '{ id: number; } | { id: number; name: string; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. -!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. \ No newline at end of file +!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypingOfArrayLiterals1.errors.txt b/tests/baselines/reference/contextualTypingOfArrayLiterals1.errors.txt index be73de51f13..4d0bf165891 100644 --- a/tests/baselines/reference/contextualTypingOfArrayLiterals1.errors.txt +++ b/tests/baselines/reference/contextualTypingOfArrayLiterals1.errors.txt @@ -1,7 +1,4 @@ -tests/cases/compiler/contextualTypingOfArrayLiterals1.ts(5,5): error TS2322: Type '(number | Date)[]' is not assignable to type 'I'. - Index signatures are incompatible. - Type 'number | Date' is not assignable to type 'Date'. - Type 'number' is not assignable to type 'Date'. +tests/cases/compiler/contextualTypingOfArrayLiterals1.ts(5,26): error TS2322: Type 'number' is not assignable to type 'Date'. ==== tests/cases/compiler/contextualTypingOfArrayLiterals1.ts (1 errors) ==== @@ -10,11 +7,9 @@ tests/cases/compiler/contextualTypingOfArrayLiterals1.ts(5,5): error TS2322: Typ } var x3: I = [new Date(), 1]; - ~~ -!!! error TS2322: Type '(number | Date)[]' is not assignable to type 'I'. -!!! error TS2322: Index signatures are incompatible. -!!! error TS2322: Type 'number | Date' is not assignable to type 'Date'. -!!! error TS2322: Type 'number' is not assignable to type 'Date'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'Date'. +!!! related TS6501 tests/cases/compiler/contextualTypingOfArrayLiterals1.ts:2:4: The expected type comes from this index signature. var r2 = x3[1]; r2.getDate(); \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt b/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt index 1bc381ec39d..693a91a1d91 100644 --- a/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt +++ b/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt @@ -1,13 +1,8 @@ -tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(4,20): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(5,23): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(6,25): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(11,40): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(16,23): error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'. - Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(4,38): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(5,41): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(6,43): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(11,51): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(16,35): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(21,22): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(26,14): error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'. @@ -17,34 +12,33 @@ tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTyp show: (x: number) => string; } function f({ show: showRename = v => v }: Show) {} - ~~~~~~~~~~ -!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:11: The expected type comes from the return type of this signature. function f2({ "show": showRename = v => v }: Show) {} - ~~~~~~~~~~ -!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:11: The expected type comes from the return type of this signature. function f3({ ["show"]: showRename = v => v }: Show) {} - ~~~~~~~~~~ -!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:11: The expected type comes from the return type of this signature. interface Nested { nested: Show } function ff({ nested: nestedRename = { show: v => v } }: Nested) {} - ~~~~ -!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. -!!! related TS6500 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:5: The expected type comes from property 'show' which is declared here on type 'Show' + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:2:11: The expected type comes from the return type of this signature. interface StringIdentity { stringIdentity(s: string): string; } let { stringIdentity: id = arg => arg.length }: StringIdentity = { stringIdentity: x => x}; - ~~ -!!! error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~~~~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6502 tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts:14:5: The expected type comes from the return type of this signature. interface Tuples { prop: [string, number]; diff --git a/tests/baselines/reference/deepElaborationsIntoArrowExpressions.errors.txt b/tests/baselines/reference/deepElaborationsIntoArrowExpressions.errors.txt new file mode 100644 index 00000000000..abaee6d6807 --- /dev/null +++ b/tests/baselines/reference/deepElaborationsIntoArrowExpressions.errors.txt @@ -0,0 +1,37 @@ +tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts(4,14): error TS2322: Type '"b"' is not assignable to type '"a"'. +tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts(12,20): error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts(16,14): error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts(18,18): error TS2322: Type 'string' is not assignable to type 'number'. + + +==== tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts (4 errors) ==== + const a: { + y(): "a" + } = { + y: () => "b" + ~~~ +!!! error TS2322: Type '"b"' is not assignable to type '"a"'. +!!! related TS6502 tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts:2:5: The expected type comes from the return type of this signature. + }; + + interface Foo { + a: number; + } + + function foo1(): () => Foo { + return () => ({a: ''}); + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! related TS6500 tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts:8:5: The expected type comes from property 'a' which is declared here on type 'Foo' + } + + function foo3(): Foo[] { + return [{a: ''}]; + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! related TS6500 tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts:8:5: The expected type comes from property 'a' which is declared here on type 'Foo' + } + var y: Foo[] = [{a: ''}] + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! related TS6500 tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts:8:5: The expected type comes from property 'a' which is declared here on type 'Foo' \ No newline at end of file diff --git a/tests/baselines/reference/deepElaborationsIntoArrowExpressions.js b/tests/baselines/reference/deepElaborationsIntoArrowExpressions.js new file mode 100644 index 00000000000..c460f56ed70 --- /dev/null +++ b/tests/baselines/reference/deepElaborationsIntoArrowExpressions.js @@ -0,0 +1,31 @@ +//// [deepElaborationsIntoArrowExpressions.ts] +const a: { + y(): "a" +} = { + y: () => "b" +}; + +interface Foo { + a: number; +} + +function foo1(): () => Foo { + return () => ({a: ''}); +} + +function foo3(): Foo[] { + return [{a: ''}]; +} +var y: Foo[] = [{a: ''}] + +//// [deepElaborationsIntoArrowExpressions.js] +const a = { + y: () => "b" +}; +function foo1() { + return () => ({ a: '' }); +} +function foo3() { + return [{ a: '' }]; +} +var y = [{ a: '' }]; diff --git a/tests/baselines/reference/deepElaborationsIntoArrowExpressions.symbols b/tests/baselines/reference/deepElaborationsIntoArrowExpressions.symbols new file mode 100644 index 00000000000..f7c07ced174 --- /dev/null +++ b/tests/baselines/reference/deepElaborationsIntoArrowExpressions.symbols @@ -0,0 +1,40 @@ +=== tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts === +const a: { +>a : Symbol(a, Decl(deepElaborationsIntoArrowExpressions.ts, 0, 5)) + + y(): "a" +>y : Symbol(y, Decl(deepElaborationsIntoArrowExpressions.ts, 0, 10)) + +} = { + y: () => "b" +>y : Symbol(y, Decl(deepElaborationsIntoArrowExpressions.ts, 2, 5)) + +}; + +interface Foo { +>Foo : Symbol(Foo, Decl(deepElaborationsIntoArrowExpressions.ts, 4, 2)) + + a: number; +>a : Symbol(Foo.a, Decl(deepElaborationsIntoArrowExpressions.ts, 6, 15)) +} + +function foo1(): () => Foo { +>foo1 : Symbol(foo1, Decl(deepElaborationsIntoArrowExpressions.ts, 8, 1)) +>Foo : Symbol(Foo, Decl(deepElaborationsIntoArrowExpressions.ts, 4, 2)) + + return () => ({a: ''}); +>a : Symbol(a, Decl(deepElaborationsIntoArrowExpressions.ts, 11, 19)) +} + +function foo3(): Foo[] { +>foo3 : Symbol(foo3, Decl(deepElaborationsIntoArrowExpressions.ts, 12, 1)) +>Foo : Symbol(Foo, Decl(deepElaborationsIntoArrowExpressions.ts, 4, 2)) + + return [{a: ''}]; +>a : Symbol(a, Decl(deepElaborationsIntoArrowExpressions.ts, 15, 13)) +} +var y: Foo[] = [{a: ''}] +>y : Symbol(y, Decl(deepElaborationsIntoArrowExpressions.ts, 17, 3)) +>Foo : Symbol(Foo, Decl(deepElaborationsIntoArrowExpressions.ts, 4, 2)) +>a : Symbol(a, Decl(deepElaborationsIntoArrowExpressions.ts, 17, 17)) + diff --git a/tests/baselines/reference/deepElaborationsIntoArrowExpressions.types b/tests/baselines/reference/deepElaborationsIntoArrowExpressions.types new file mode 100644 index 00000000000..2af9c1e978d --- /dev/null +++ b/tests/baselines/reference/deepElaborationsIntoArrowExpressions.types @@ -0,0 +1,49 @@ +=== tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts === +const a: { +>a : { y(): "a"; } + + y(): "a" +>y : () => "a" + +} = { +>{ y: () => "b"} : { y: () => "b"; } + + y: () => "b" +>y : () => "b" +>() => "b" : () => "b" +>"b" : "b" + +}; + +interface Foo { + a: number; +>a : number +} + +function foo1(): () => Foo { +>foo1 : () => () => Foo + + return () => ({a: ''}); +>() => ({a: ''}) : () => { a: string; } +>({a: ''}) : { a: string; } +>{a: ''} : { a: string; } +>a : string +>'' : "" +} + +function foo3(): Foo[] { +>foo3 : () => Foo[] + + return [{a: ''}]; +>[{a: ''}] : { a: string; }[] +>{a: ''} : { a: string; } +>a : string +>'' : "" +} +var y: Foo[] = [{a: ''}] +>y : Foo[] +>[{a: ''}] : { a: string; }[] +>{a: ''} : { a: string; } +>a : string +>'' : "" + diff --git a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt index 46e4f597c21..d970223cb1c 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt @@ -5,9 +5,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts( tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(22,11): error TS2322: Type 'string' is not assignable to type '[[any]]'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(23,4): error TS2345: Argument of type '[number, number]' is not assignable to parameter of type '[any, any, [[any]]]'. Property '2' is missing in type '[number, number]'. -tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(24,4): error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(24,11): error TS2322: Type 'string' is not assignable to type 'number'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(29,17): error TS1317: A parameter property cannot be declared using a rest parameter. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(34,22): error TS2304: Cannot find name 'E1'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(34,28): error TS2304: Cannot find name 'E'. @@ -52,10 +50,8 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts( !!! error TS2345: Argument of type '[number, number]' is not assignable to parameter of type '[any, any, [[any]]]'. !!! error TS2345: Property '2' is missing in type '[number, number]'. a6([1, 2, "string"]); // Error, parameter type is number[] - ~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. -!!! error TS2345: Type 'string | number' is not assignable to type 'number'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. + ~~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. var temp = [1, 2, 3]; diff --git a/tests/baselines/reference/destructuringVariableDeclaration2.errors.txt b/tests/baselines/reference/destructuringVariableDeclaration2.errors.txt index 104c95bc427..2ea3149f2ed 100644 --- a/tests/baselines/reference/destructuringVariableDeclaration2.errors.txt +++ b/tests/baselines/reference/destructuringVariableDeclaration2.errors.txt @@ -1,8 +1,7 @@ tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(3,46): error TS2322: Type 'true' is not assignable to type 'number'. tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(3,56): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(4,61): error TS2322: Type 'false' is not assignable to type 'string'. -tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(19,10): error TS2322: Type 'string[]' is not assignable to type 'number[]'. - Type 'string' is not assignable to type 'number'. +tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(19,16): error TS2322: Type 'string' is not assignable to type 'number'. ==== tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts (4 errors) ==== @@ -33,6 +32,5 @@ tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(1 // an initializer expression, the type of the initializer expression is required to be assignable // to the widened form of the type associated with the destructuring variable declaration, binding property, or binding element. var {d: {d1 = ["string", null]}}: { d: { d1: number[] } } = { d: { d1: [1, 2] } }; // Error - ~~ -!!! error TS2322: Type 'string[]' is not assignable to type 'number[]'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file + ~~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/everyTypeWithAnnotationAndInvalidInitializer.errors.txt b/tests/baselines/reference/everyTypeWithAnnotationAndInvalidInitializer.errors.txt index 0da83390f8e..81a3ceab8ef 100644 --- a/tests/baselines/reference/everyTypeWithAnnotationAndInvalidInitializer.errors.txt +++ b/tests/baselines/reference/everyTypeWithAnnotationAndInvalidInitializer.errors.txt @@ -18,8 +18,7 @@ tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAnd tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(47,5): error TS2322: Type '(x: number) => boolean' is not assignable to type '(x: string) => number'. Types of parameters 'x' and 'x' are incompatible. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(48,5): error TS2322: Type '(x: string) => string' is not assignable to type '(x: string) => number'. - Type 'string' is not assignable to type 'number'. +tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(48,32): error TS2322: Type 'string' is not assignable to type 'number'. tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(50,5): error TS2322: Type 'typeof N' is not assignable to type 'typeof M'. Types of property 'A' are incompatible. Type 'typeof N.A' is not assignable to type 'typeof M.A'. @@ -111,9 +110,9 @@ tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAnd !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. !!! error TS2322: Type 'string' is not assignable to type 'number'. var aLambda: typeof F = (x) => 'a string'; - ~~~~~~~ -!!! error TS2322: Type '(x: string) => string' is not assignable to type '(x: string) => number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. + ~~~~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! related TS6502 tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts:15:10: The expected type comes from the return type of this signature. var aModule: typeof M = N; ~~~~~~~ diff --git a/tests/baselines/reference/fixingTypeParametersRepeatedly2.errors.txt b/tests/baselines/reference/fixingTypeParametersRepeatedly2.errors.txt index 900d605d5fc..d295f836605 100644 --- a/tests/baselines/reference/fixingTypeParametersRepeatedly2.errors.txt +++ b/tests/baselines/reference/fixingTypeParametersRepeatedly2.errors.txt @@ -1,6 +1,5 @@ -tests/cases/compiler/fixingTypeParametersRepeatedly2.ts(11,27): error TS2345: Argument of type '(d: Derived) => Base' is not assignable to parameter of type '(p: Derived) => Derived'. - Type 'Base' is not assignable to type 'Derived'. - Property 'toBase' is missing in type 'Base'. +tests/cases/compiler/fixingTypeParametersRepeatedly2.ts(11,32): error TS2322: Type 'Base' is not assignable to type 'Derived'. + Property 'toBase' is missing in type 'Base'. ==== tests/cases/compiler/fixingTypeParametersRepeatedly2.ts (1 errors) ==== @@ -15,10 +14,10 @@ tests/cases/compiler/fixingTypeParametersRepeatedly2.ts(11,27): error TS2345: Ar declare function foo(x: T, func: (p: T) => T): T; var result = foo(derived, d => d.toBase()); - ~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '(d: Derived) => Base' is not assignable to parameter of type '(p: Derived) => Derived'. -!!! error TS2345: Type 'Base' is not assignable to type 'Derived'. -!!! error TS2345: Property 'toBase' is missing in type 'Base'. + ~~~~~~~~~~ +!!! error TS2322: Type 'Base' is not assignable to type 'Derived'. +!!! error TS2322: Property 'toBase' is missing in type 'Base'. +!!! related TS6502 tests/cases/compiler/fixingTypeParametersRepeatedly2.ts:10:37: The expected type comes from the return type of this signature. // bar should type check just like foo. // The same error should be observed in both cases. diff --git a/tests/baselines/reference/for-of10.errors.txt b/tests/baselines/reference/for-of10.errors.txt index 1636f1a02d0..724b02dce69 100644 --- a/tests/baselines/reference/for-of10.errors.txt +++ b/tests/baselines/reference/for-of10.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/es6/for-ofStatements/for-of10.ts(2,6): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/es6/for-ofStatements/for-of10.ts(2,12): error TS2322: Type 'number' is not assignable to type 'string'. ==== tests/cases/conformance/es6/for-ofStatements/for-of10.ts (1 errors) ==== var v: string; for (v of [0]) { } - ~ + ~ !!! error TS2322: Type 'number' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/for-of11.errors.txt b/tests/baselines/reference/for-of11.errors.txt index dc527e73efe..98721081433 100644 --- a/tests/baselines/reference/for-of11.errors.txt +++ b/tests/baselines/reference/for-of11.errors.txt @@ -1,10 +1,8 @@ -tests/cases/conformance/es6/for-ofStatements/for-of11.ts(2,6): error TS2322: Type 'string | number' is not assignable to type 'string'. - Type 'number' is not assignable to type 'string'. +tests/cases/conformance/es6/for-ofStatements/for-of11.ts(2,12): error TS2322: Type 'number' is not assignable to type 'string'. ==== tests/cases/conformance/es6/for-ofStatements/for-of11.ts (1 errors) ==== var v: string; for (v of [0, ""]) { } - ~ -!!! error TS2322: Type 'string | number' is not assignable to type 'string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. \ No newline at end of file + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/for-of39.errors.txt b/tests/baselines/reference/for-of39.errors.txt index 5f084961833..fedf9f3e343 100644 --- a/tests/baselines/reference/for-of39.errors.txt +++ b/tests/baselines/reference/for-of39.errors.txt @@ -1,16 +1,10 @@ -tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,19): error TS2345: Argument of type '([string, number] | [string, true])[]' is not assignable to parameter of type 'ReadonlyArray<[string, boolean]>'. - Type '[string, number] | [string, true]' is not assignable to type '[string, boolean]'. - Type '[string, number]' is not assignable to type '[string, boolean]'. - Type 'number' is not assignable to type 'boolean'. +tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,37): error TS2322: Type 'number' is not assignable to type 'boolean'. ==== tests/cases/conformance/es6/for-ofStatements/for-of39.ts (1 errors) ==== var map = new Map([["", true], ["", 0]]); - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '([string, number] | [string, true])[]' is not assignable to parameter of type 'ReadonlyArray<[string, boolean]>'. -!!! error TS2345: Type '[string, number] | [string, true]' is not assignable to type '[string, boolean]'. -!!! error TS2345: Type '[string, number]' is not assignable to type '[string, boolean]'. -!!! error TS2345: Type 'number' is not assignable to type 'boolean'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'boolean'. for (var [k, v] of map) { k; v; diff --git a/tests/baselines/reference/functionOverloads40.errors.txt b/tests/baselines/reference/functionOverloads40.errors.txt index f965a4eb9e1..f053c7c6208 100644 --- a/tests/baselines/reference/functionOverloads40.errors.txt +++ b/tests/baselines/reference/functionOverloads40.errors.txt @@ -1,7 +1,4 @@ -tests/cases/compiler/functionOverloads40.ts(4,13): error TS2345: Argument of type '{ a: string; }[]' is not assignable to parameter of type '{ a: boolean; }[]'. - Type '{ a: string; }' is not assignable to type '{ a: boolean; }'. - Types of property 'a' are incompatible. - Type 'string' is not assignable to type 'boolean'. +tests/cases/compiler/functionOverloads40.ts(4,15): error TS2322: Type 'string' is not assignable to type 'boolean'. ==== tests/cases/compiler/functionOverloads40.ts (1 errors) ==== @@ -9,9 +6,7 @@ tests/cases/compiler/functionOverloads40.ts(4,13): error TS2345: Argument of typ function foo(bar:{a:boolean;}[]):number; function foo(bar:{a:any;}[]):any{ return bar } var x = foo([{a:'bar'}]); - ~~~~~~~~~~~ -!!! error TS2345: Argument of type '{ a: string; }[]' is not assignable to parameter of type '{ a: boolean; }[]'. -!!! error TS2345: Type '{ a: string; }' is not assignable to type '{ a: boolean; }'. -!!! error TS2345: Types of property 'a' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type 'boolean'. + ~ +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. +!!! related TS6500 tests/cases/compiler/functionOverloads40.ts:2:19: The expected type comes from property 'a' which is declared here on type '{ a: boolean; }' \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads41.errors.txt b/tests/baselines/reference/functionOverloads41.errors.txt index 77f8149c822..a3d924f15bc 100644 --- a/tests/baselines/reference/functionOverloads41.errors.txt +++ b/tests/baselines/reference/functionOverloads41.errors.txt @@ -1,6 +1,5 @@ -tests/cases/compiler/functionOverloads41.ts(4,13): error TS2345: Argument of type '{}[]' is not assignable to parameter of type '{ a: boolean; }[]'. - Type '{}' is not assignable to type '{ a: boolean; }'. - Property 'a' is missing in type '{}'. +tests/cases/compiler/functionOverloads41.ts(4,14): error TS2322: Type '{}' is not assignable to type '{ a: boolean; }'. + Property 'a' is missing in type '{}'. ==== tests/cases/compiler/functionOverloads41.ts (1 errors) ==== @@ -8,8 +7,7 @@ tests/cases/compiler/functionOverloads41.ts(4,13): error TS2345: Argument of typ function foo(bar:{a:boolean;}[]):number; function foo(bar:{a:any;}[]):any{ return bar } var x = foo([{}]); - ~~~~ -!!! error TS2345: Argument of type '{}[]' is not assignable to parameter of type '{ a: boolean; }[]'. -!!! error TS2345: Type '{}' is not assignable to type '{ a: boolean; }'. -!!! error TS2345: Property 'a' is missing in type '{}'. + ~~ +!!! error TS2322: Type '{}' is not assignable to type '{ a: boolean; }'. +!!! error TS2322: Property 'a' is missing in type '{}'. \ No newline at end of file diff --git a/tests/baselines/reference/genericCallWithGenericSignatureArguments2.errors.txt b/tests/baselines/reference/genericCallWithGenericSignatureArguments2.errors.txt index 363f0b0f645..a66672f5151 100644 --- a/tests/baselines/reference/genericCallWithGenericSignatureArguments2.errors.txt +++ b/tests/baselines/reference/genericCallWithGenericSignatureArguments2.errors.txt @@ -6,8 +6,7 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGen tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments2.ts(25,23): error TS2345: Argument of type '(a: T) => T' is not assignable to parameter of type '(x: Date) => Date'. Types of parameters 'a' and 'x' are incompatible. Type 'Date' is not assignable to type 'T'. -tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments2.ts(37,36): error TS2345: Argument of type '(x: E) => F' is not assignable to parameter of type '(x: E) => E'. - Type 'F' is not assignable to type 'E'. +tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments2.ts(37,43): error TS2322: Type 'F' is not assignable to type 'E'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments2.ts(50,21): error TS2345: Argument of type 'Date' is not assignable to parameter of type 'T'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments2.ts(51,22): error TS2345: Argument of type '1' is not assignable to parameter of type 'T'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments2.ts(60,23): error TS2345: Argument of type '(a: T) => T' is not assignable to parameter of type '(x: Date) => Date'. @@ -67,9 +66,9 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGen } var r7 = foo3(E.A, (x) => E.A, (x) => F.A); // error - ~~~~~~~~~~ -!!! error TS2345: Argument of type '(x: E) => F' is not assignable to parameter of type '(x: E) => E'. -!!! error TS2345: Type 'F' is not assignable to type 'E'. + ~~~ +!!! error TS2322: Type 'F' is not assignable to type 'E'. +!!! related TS6502 tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments2.ts:32:47: The expected type comes from the return type of this signature. } module TU { diff --git a/tests/baselines/reference/heterogeneousArrayAndOverloads.errors.txt b/tests/baselines/reference/heterogeneousArrayAndOverloads.errors.txt index e5c2be7a598..60228b956f9 100644 --- a/tests/baselines/reference/heterogeneousArrayAndOverloads.errors.txt +++ b/tests/baselines/reference/heterogeneousArrayAndOverloads.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/heterogeneousArrayAndOverloads.ts(9,19): error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'string[]'. - Type 'string | number' is not assignable to type 'string'. - Type 'number' is not assignable to type 'string'. +tests/cases/compiler/heterogeneousArrayAndOverloads.ts(9,20): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/heterogeneousArrayAndOverloads.ts(9,23): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/heterogeneousArrayAndOverloads.ts(9,32): error TS2322: Type 'number' is not assignable to type 'string'. -==== tests/cases/compiler/heterogeneousArrayAndOverloads.ts (1 errors) ==== +==== tests/cases/compiler/heterogeneousArrayAndOverloads.ts (3 errors) ==== class arrTest { test(arg1: number[]); test(arg1: string[]); @@ -13,9 +13,11 @@ tests/cases/compiler/heterogeneousArrayAndOverloads.ts(9,19): error TS2345: Argu this.test(["hi"]); this.test([]); this.test([1, 2, "hi", 5]); // Error - ~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'string[]'. -!!! error TS2345: Type 'string | number' is not assignable to type 'string'. -!!! error TS2345: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. } } \ No newline at end of file diff --git a/tests/baselines/reference/iterableArrayPattern28.errors.txt b/tests/baselines/reference/iterableArrayPattern28.errors.txt index ecc9f0a02c5..26ce99e048a 100644 --- a/tests/baselines/reference/iterableArrayPattern28.errors.txt +++ b/tests/baselines/reference/iterableArrayPattern28.errors.txt @@ -1,8 +1,5 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(1,33): error TS2501: A rest element cannot contain a binding pattern. -tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,32): error TS2345: Argument of type '([string, number] | [string, boolean])[]' is not assignable to parameter of type 'ReadonlyArray<[string, number]>'. - Type '[string, number] | [string, boolean]' is not assignable to type '[string, number]'. - Type '[string, boolean]' is not assignable to type '[string, number]'. - Type 'boolean' is not assignable to type 'number'. +tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,52): error TS2322: Type 'true' is not assignable to type 'number'. ==== tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts (2 errors) ==== @@ -10,8 +7,5 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,32): error ~~~~~~~~~~~~~~~~~~~~ !!! error TS2501: A rest element cannot contain a binding pattern. takeFirstTwoEntries(...new Map([["", 0], ["hello", true]])); - ~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '([string, number] | [string, boolean])[]' is not assignable to parameter of type 'ReadonlyArray<[string, number]>'. -!!! error TS2345: Type '[string, number] | [string, boolean]' is not assignable to type '[string, number]'. -!!! error TS2345: Type '[string, boolean]' is not assignable to type '[string, number]'. -!!! error TS2345: Type 'boolean' is not assignable to type 'number'. \ No newline at end of file + ~~~~ +!!! error TS2322: Type 'true' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/iteratorSpreadInArray5.errors.txt b/tests/baselines/reference/iteratorSpreadInArray5.errors.txt index 02049824c4f..9d8b980d0b2 100644 --- a/tests/baselines/reference/iteratorSpreadInArray5.errors.txt +++ b/tests/baselines/reference/iteratorSpreadInArray5.errors.txt @@ -1,6 +1,4 @@ -tests/cases/conformance/es6/spread/iteratorSpreadInArray5.ts(14,5): error TS2322: Type '(number | symbol)[]' is not assignable to type 'number[]'. - Type 'number | symbol' is not assignable to type 'number'. - Type 'symbol' is not assignable to type 'number'. +tests/cases/conformance/es6/spread/iteratorSpreadInArray5.ts(14,30): error TS2322: Type 'symbol' is not assignable to type 'number'. ==== tests/cases/conformance/es6/spread/iteratorSpreadInArray5.ts (1 errors) ==== @@ -18,7 +16,5 @@ tests/cases/conformance/es6/spread/iteratorSpreadInArray5.ts(14,5): error TS2322 } var array: number[] = [0, 1, ...new SymbolIterator]; - ~~~~~ -!!! error TS2322: Type '(number | symbol)[]' is not assignable to type 'number[]'. -!!! error TS2322: Type 'number | symbol' is not assignable to type 'number'. -!!! error TS2322: Type 'symbol' is not assignable to type 'number'. \ No newline at end of file + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'symbol' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt b/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt index f9e193d104b..68837c6e1fb 100644 --- a/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt +++ b/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt @@ -1,5 +1,4 @@ -tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(20,31): error TS2322: Type '(p: LitProps<"x">) => "y"' is not assignable to type '(x: IntrinsicAttributes & LitProps<"x">) => "x"'. - Type '"y"' is not assignable to type '"x"'. +tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(20,46): error TS2322: Type '"y"' is not assignable to type '"x"'. tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(21,19): error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x" | "y">'. Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'LitProps<"x" | "y">'. Types of property 'children' are incompatible. @@ -38,10 +37,9 @@ tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(22,21): error TS2322: // Should error const arg = "y"} /> - ~~~~~~~~ -!!! error TS2322: Type '(p: LitProps<"x">) => "y"' is not assignable to type '(x: IntrinsicAttributes & LitProps<"x">) => "x"'. -!!! error TS2322: Type '"y"' is not assignable to type '"x"'. -!!! related TS6500 tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx:13:34: The expected type comes from property 'children' which is declared here on type 'IntrinsicAttributes & LitProps<"x">' + ~~~ +!!! error TS2322: Type '"y"' is not assignable to type '"x"'. +!!! related TS6502 tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx:13:44: The expected type comes from the return type of this signature. const argchild = {p => "y"} ~~~~~~~ !!! error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x" | "y">'. diff --git a/tests/baselines/reference/keyofIsLiteralContexualType.errors.txt b/tests/baselines/reference/keyofIsLiteralContexualType.errors.txt index b578d002e05..92f3d403d02 100644 --- a/tests/baselines/reference/keyofIsLiteralContexualType.errors.txt +++ b/tests/baselines/reference/keyofIsLiteralContexualType.errors.txt @@ -1,7 +1,5 @@ -tests/cases/compiler/keyofIsLiteralContexualType.ts(5,9): error TS2322: Type '("a" | "b" | "c")[]' is not assignable to type '(keyof T)[]'. - Type '"a" | "b" | "c"' is not assignable to type 'keyof T'. - Type '"c"' is not assignable to type 'keyof T'. - Type '"c"' is not assignable to type '"a" | "b"'. +tests/cases/compiler/keyofIsLiteralContexualType.ts(5,37): error TS2322: Type '"c"' is not assignable to type 'keyof T'. + Type '"c"' is not assignable to type '"a" | "b"'. tests/cases/compiler/keyofIsLiteralContexualType.ts(13,11): error TS2339: Property 'b' does not exist on type 'Pick<{ a: number; b: number; c: number; }, "a" | "c">'. @@ -11,11 +9,9 @@ tests/cases/compiler/keyofIsLiteralContexualType.ts(13,11): error TS2339: Proper function foo() { let a: (keyof T)[] = ["a", "b"]; let b: (keyof T)[] = ["a", "b", "c"]; - ~ -!!! error TS2322: Type '("a" | "b" | "c")[]' is not assignable to type '(keyof T)[]'. -!!! error TS2322: Type '"a" | "b" | "c"' is not assignable to type 'keyof T'. -!!! error TS2322: Type '"c"' is not assignable to type 'keyof T'. -!!! error TS2322: Type '"c"' is not assignable to type '"a" | "b"'. + ~~~ +!!! error TS2322: Type '"c"' is not assignable to type 'keyof T'. +!!! error TS2322: Type '"c"' is not assignable to type '"a" | "b"'. } // Repro from #12455 diff --git a/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt b/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt index f96dc69ee33..1dace59f722 100644 --- a/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt +++ b/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt @@ -1,6 +1,4 @@ -tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(10,30): error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. +tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(10,34): error TS2322: Type 'string' is not assignable to type 'number'. tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(11,15): error TS2558: Expected 2 type arguments, but got 1. @@ -15,10 +13,8 @@ tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(11,15): e var r5 = map([1, ""], (x) => x.toString()); var r6 = map([1, ""], (x) => x.toString()); var r7 = map([1, ""], (x) => x.toString()); // error - ~~~~~~~ -!!! error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. -!!! error TS2345: Type 'string | number' is not assignable to type 'number'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. + ~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. var r7b = map([1, ""], (x) => x.toString()); // error ~~~~~~ !!! error TS2558: Expected 2 type arguments, but got 1. diff --git a/tests/baselines/reference/objectLiteralFunctionArgContextualTyping2.errors.txt b/tests/baselines/reference/objectLiteralFunctionArgContextualTyping2.errors.txt index 9fa7176779f..3c3d292216b 100644 --- a/tests/baselines/reference/objectLiteralFunctionArgContextualTyping2.errors.txt +++ b/tests/baselines/reference/objectLiteralFunctionArgContextualTyping2.errors.txt @@ -32,12 +32,9 @@ tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(13,17): error f2({ toString: (s) => s }) ~~~~~~~~ !!! error TS2322: Type '(s: any) => any' is not assignable to type '() => string'. -!!! related TS6500 /.ts/lib.es5.d.ts:125:5: The expected type comes from property 'toString' which is declared here on type 'I2' f2({ toString: (s: string) => s }) ~~~~~~~~ !!! error TS2322: Type '(s: string) => string' is not assignable to type '() => string'. -!!! related TS6500 /.ts/lib.es5.d.ts:125:5: The expected type comes from property 'toString' which is declared here on type 'I2' f2({ value: '', toString: (s) => s.uhhh }) ~~~~~~~~ -!!! error TS2322: Type '(s: any) => any' is not assignable to type '() => string'. -!!! related TS6500 /.ts/lib.es5.d.ts:125:5: The expected type comes from property 'toString' which is declared here on type 'I2' \ No newline at end of file +!!! error TS2322: Type '(s: any) => any' is not assignable to type '() => string'. \ No newline at end of file diff --git a/tests/baselines/reference/objectLiteralsAgainstUnionsOfArrays01.errors.txt b/tests/baselines/reference/objectLiteralsAgainstUnionsOfArrays01.errors.txt index 13cc52dd2c6..5260d6a8da6 100644 --- a/tests/baselines/reference/objectLiteralsAgainstUnionsOfArrays01.errors.txt +++ b/tests/baselines/reference/objectLiteralsAgainstUnionsOfArrays01.errors.txt @@ -1,10 +1,7 @@ -tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts(9,5): error TS2322: Type '{ bar: { prop: number; }; }[]' is not assignable to type 'Foo[]'. - Type '{ bar: { prop: number; }; }' is not assignable to type 'Foo'. - Types of property 'bar' are incompatible. - Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'. - Type '{ prop: number; }' is not assignable to type 'Bar'. - Types of property 'prop' are incompatible. - Type 'number' is not assignable to type 'string'. +tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts(10,5): error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'. + Type '{ prop: number; }' is not assignable to type 'Bar'. + Types of property 'prop' are incompatible. + Type 'number' is not assignable to type 'string'. ==== tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts (1 errors) ==== @@ -17,14 +14,12 @@ tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts(9,5): error TS2322 } let x: Foo[] = [ - ~ -!!! error TS2322: Type '{ bar: { prop: number; }; }[]' is not assignable to type 'Foo[]'. -!!! error TS2322: Type '{ bar: { prop: number; }; }' is not assignable to type 'Foo'. -!!! error TS2322: Types of property 'bar' are incompatible. -!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'. -!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar'. -!!! error TS2322: Types of property 'prop' are incompatible. -!!! error TS2322: Type 'number' is not assignable to type 'string'. { bar: { prop: 100 } } + ~~~ +!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'. +!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar'. +!!! error TS2322: Types of property 'prop' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6500 tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts:2:3: The expected type comes from property 'bar' which is declared here on type 'Foo' ] \ No newline at end of file diff --git a/tests/baselines/reference/overloadResolutionOverCTLambda.errors.txt b/tests/baselines/reference/overloadResolutionOverCTLambda.errors.txt index 9fc11b681c7..c76eae5908c 100644 --- a/tests/baselines/reference/overloadResolutionOverCTLambda.errors.txt +++ b/tests/baselines/reference/overloadResolutionOverCTLambda.errors.txt @@ -1,10 +1,9 @@ -tests/cases/compiler/overloadResolutionOverCTLambda.ts(2,5): error TS2345: Argument of type '(a: number) => number' is not assignable to parameter of type '(item: number) => boolean'. - Type 'number' is not assignable to type 'boolean'. +tests/cases/compiler/overloadResolutionOverCTLambda.ts(2,10): error TS2322: Type 'number' is not assignable to type 'boolean'. ==== tests/cases/compiler/overloadResolutionOverCTLambda.ts (1 errors) ==== function foo(b: (item: number) => boolean) { } foo(a => a); // can not convert (number)=>bool to (number)=>number - ~~~~~~ -!!! error TS2345: Argument of type '(a: number) => number' is not assignable to parameter of type '(item: number) => boolean'. -!!! error TS2345: Type 'number' is not assignable to type 'boolean'. \ No newline at end of file + ~ +!!! error TS2322: Type 'number' is not assignable to type 'boolean'. +!!! related TS6502 tests/cases/compiler/overloadResolutionOverCTLambda.ts:1:17: The expected type comes from the return type of this signature. \ No newline at end of file diff --git a/tests/baselines/reference/overloadResolutionTest1.errors.txt b/tests/baselines/reference/overloadResolutionTest1.errors.txt index 53ee7873472..008ee13127c 100644 --- a/tests/baselines/reference/overloadResolutionTest1.errors.txt +++ b/tests/baselines/reference/overloadResolutionTest1.errors.txt @@ -1,7 +1,4 @@ -tests/cases/compiler/overloadResolutionTest1.ts(7,16): error TS2345: Argument of type '{ a: string; }[]' is not assignable to parameter of type '{ a: boolean; }[]'. - Type '{ a: string; }' is not assignable to type '{ a: boolean; }'. - Types of property 'a' are incompatible. - Type 'string' is not assignable to type 'boolean'. +tests/cases/compiler/overloadResolutionTest1.ts(7,18): error TS2322: Type 'string' is not assignable to type 'boolean'. tests/cases/compiler/overloadResolutionTest1.ts(18,16): error TS2322: Type 'string' is not assignable to type 'boolean'. tests/cases/compiler/overloadResolutionTest1.ts(24,15): error TS2322: Type 'true' is not assignable to type 'string'. @@ -14,11 +11,9 @@ tests/cases/compiler/overloadResolutionTest1.ts(24,15): error TS2322: Type 'true var x1 = foo([{a:true}]); // works var x11 = foo([{a:0}]); // works var x111 = foo([{a:"s"}]); // error - does not match any signature - ~~~~~~~~~ -!!! error TS2345: Argument of type '{ a: string; }[]' is not assignable to parameter of type '{ a: boolean; }[]'. -!!! error TS2345: Type '{ a: string; }' is not assignable to type '{ a: boolean; }'. -!!! error TS2345: Types of property 'a' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type 'boolean'. + ~ +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. +!!! related TS6500 tests/cases/compiler/overloadResolutionTest1.ts:2:19: The expected type comes from property 'a' which is declared here on type '{ a: boolean; }' var x1111 = foo([{a:null}]); // works - ambiguous call is resolved to be the first in the overload set so this returns a string diff --git a/tests/baselines/reference/overloadsWithProvisionalErrors.errors.txt b/tests/baselines/reference/overloadsWithProvisionalErrors.errors.txt index daf057c9ebd..aa247f0bd96 100644 --- a/tests/baselines/reference/overloadsWithProvisionalErrors.errors.txt +++ b/tests/baselines/reference/overloadsWithProvisionalErrors.errors.txt @@ -1,10 +1,8 @@ -tests/cases/compiler/overloadsWithProvisionalErrors.ts(6,6): error TS2345: Argument of type '(s: string) => {}' is not assignable to parameter of type '(s: string) => { a: number; b: number; }'. - Type '{}' is not assignable to type '{ a: number; b: number; }'. - Property 'a' is missing in type '{}'. +tests/cases/compiler/overloadsWithProvisionalErrors.ts(6,11): error TS2322: Type '{}' is not assignable to type '{ a: number; b: number; }'. + Property 'a' is missing in type '{}'. tests/cases/compiler/overloadsWithProvisionalErrors.ts(7,17): error TS2304: Cannot find name 'blah'. -tests/cases/compiler/overloadsWithProvisionalErrors.ts(8,6): error TS2345: Argument of type '(s: string) => { a: any; }' is not assignable to parameter of type '(s: string) => { a: number; b: number; }'. - Type '{ a: any; }' is not assignable to type '{ a: number; b: number; }'. - Property 'b' is missing in type '{ a: any; }'. +tests/cases/compiler/overloadsWithProvisionalErrors.ts(8,11): error TS2322: Type '{ a: any; }' is not assignable to type '{ a: number; b: number; }'. + Property 'b' is missing in type '{ a: any; }'. tests/cases/compiler/overloadsWithProvisionalErrors.ts(8,17): error TS2304: Cannot find name 'blah'. @@ -15,17 +13,17 @@ tests/cases/compiler/overloadsWithProvisionalErrors.ts(8,17): error TS2304: Cann }; func(s => ({})); // Error for no applicable overload (object type is missing a and b) - ~~~~~~~~~ -!!! error TS2345: Argument of type '(s: string) => {}' is not assignable to parameter of type '(s: string) => { a: number; b: number; }'. -!!! error TS2345: Type '{}' is not assignable to type '{ a: number; b: number; }'. -!!! error TS2345: Property 'a' is missing in type '{}'. + ~~~~ +!!! error TS2322: Type '{}' is not assignable to type '{ a: number; b: number; }'. +!!! error TS2322: Property 'a' is missing in type '{}'. +!!! related TS6502 tests/cases/compiler/overloadsWithProvisionalErrors.ts:3:14: The expected type comes from the return type of this signature. func(s => ({ a: blah, b: 3 })); // Only error inside the function, but not outside (since it would be applicable if not for the provisional error) ~~~~ !!! error TS2304: Cannot find name 'blah'. func(s => ({ a: blah })); // Two errors here, one for blah not being defined, and one for the overload since it would not be applicable anyway - ~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '(s: string) => { a: any; }' is not assignable to parameter of type '(s: string) => { a: number; b: number; }'. -!!! error TS2345: Type '{ a: any; }' is not assignable to type '{ a: number; b: number; }'. -!!! error TS2345: Property 'b' is missing in type '{ a: any; }'. + ~~~~~~~~~~~~~ +!!! error TS2322: Type '{ a: any; }' is not assignable to type '{ a: number; b: number; }'. +!!! error TS2322: Property 'b' is missing in type '{ a: any; }'. +!!! related TS6502 tests/cases/compiler/overloadsWithProvisionalErrors.ts:3:14: The expected type comes from the return type of this signature. ~~~~ !!! error TS2304: Cannot find name 'blah'. \ No newline at end of file diff --git a/tests/baselines/reference/promiseChaining1.errors.txt b/tests/baselines/reference/promiseChaining1.errors.txt index 7396d03059a..95f421b36f0 100644 --- a/tests/baselines/reference/promiseChaining1.errors.txt +++ b/tests/baselines/reference/promiseChaining1.errors.txt @@ -1,5 +1,4 @@ -tests/cases/compiler/promiseChaining1.ts(7,50): error TS2345: Argument of type '(x: S) => string' is not assignable to parameter of type '(x: S) => Function'. - Type 'string' is not assignable to type 'Function'. +tests/cases/compiler/promiseChaining1.ts(7,55): error TS2322: Type 'string' is not assignable to type 'Function'. ==== tests/cases/compiler/promiseChaining1.ts (1 errors) ==== @@ -10,9 +9,9 @@ tests/cases/compiler/promiseChaining1.ts(7,50): error TS2345: Argument of type ' var result = cb(this.value); // should get a fresh type parameter which each then call var z = this.then(x => result)/*S*/.then(x => "abc")/*Function*/.then(x => x.length)/*number*/; // Should error on "abc" because it is not a Function - ~~~~~~~~~~ -!!! error TS2345: Argument of type '(x: S) => string' is not assignable to parameter of type '(x: S) => Function'. -!!! error TS2345: Type 'string' is not assignable to type 'Function'. + ~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Function'. +!!! related TS6502 tests/cases/compiler/promiseChaining1.ts:4:34: The expected type comes from the return type of this signature. return new Chain2(result); } } \ No newline at end of file diff --git a/tests/baselines/reference/promiseChaining2.errors.txt b/tests/baselines/reference/promiseChaining2.errors.txt index a31c4335da7..f7326ec8cbd 100644 --- a/tests/baselines/reference/promiseChaining2.errors.txt +++ b/tests/baselines/reference/promiseChaining2.errors.txt @@ -1,5 +1,4 @@ -tests/cases/compiler/promiseChaining2.ts(7,45): error TS2345: Argument of type '(x: S) => string' is not assignable to parameter of type '(x: S) => Function'. - Type 'string' is not assignable to type 'Function'. +tests/cases/compiler/promiseChaining2.ts(7,50): error TS2322: Type 'string' is not assignable to type 'Function'. ==== tests/cases/compiler/promiseChaining2.ts (1 errors) ==== @@ -10,9 +9,9 @@ tests/cases/compiler/promiseChaining2.ts(7,45): error TS2345: Argument of type ' var result = cb(this.value); // should get a fresh type parameter which each then call var z = this.then(x => result).then(x => "abc").then(x => x.length); - ~~~~~~~~~~ -!!! error TS2345: Argument of type '(x: S) => string' is not assignable to parameter of type '(x: S) => Function'. -!!! error TS2345: Type 'string' is not assignable to type 'Function'. + ~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'Function'. +!!! related TS6502 tests/cases/compiler/promiseChaining2.ts:4:34: The expected type comes from the return type of this signature. return new Chain2(result); } } \ No newline at end of file diff --git a/tests/baselines/reference/promiseTypeInference.errors.txt b/tests/baselines/reference/promiseTypeInference.errors.txt index fab56c73375..0ae42f3cbbd 100644 --- a/tests/baselines/reference/promiseTypeInference.errors.txt +++ b/tests/baselines/reference/promiseTypeInference.errors.txt @@ -1,11 +1,10 @@ -tests/cases/compiler/promiseTypeInference.ts(10,34): error TS2345: Argument of type '(s: string) => IPromise' is not assignable to parameter of type '(value: string) => number | PromiseLike'. - Type 'IPromise' is not assignable to type 'number | PromiseLike'. - Type 'IPromise' is not assignable to type 'PromiseLike'. - Types of property 'then' are incompatible. - Type '(success?: (value: number) => IPromise) => IPromise' is not assignable to type '(onfulfilled?: (value: number) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => PromiseLike'. - Types of parameters 'success' and 'onfulfilled' are incompatible. - Type 'TResult1 | PromiseLike' is not assignable to type 'IPromise'. - Type 'TResult1' is not assignable to type 'IPromise'. +tests/cases/compiler/promiseTypeInference.ts(10,39): error TS2322: Type 'IPromise' is not assignable to type 'number | PromiseLike'. + Type 'IPromise' is not assignable to type 'PromiseLike'. + Types of property 'then' are incompatible. + Type '(success?: (value: number) => IPromise) => IPromise' is not assignable to type '(onfulfilled?: (value: number) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => PromiseLike'. + Types of parameters 'success' and 'onfulfilled' are incompatible. + Type 'TResult1 | PromiseLike' is not assignable to type 'IPromise'. + Type 'TResult1' is not assignable to type 'IPromise'. ==== tests/cases/compiler/promiseTypeInference.ts (1 errors) ==== @@ -19,13 +18,13 @@ tests/cases/compiler/promiseTypeInference.ts(10,34): error TS2345: Argument of t declare function convert(s: string): IPromise; var $$x = load("something").then(s => convert(s)); - ~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '(s: string) => IPromise' is not assignable to parameter of type '(value: string) => number | PromiseLike'. -!!! error TS2345: Type 'IPromise' is not assignable to type 'number | PromiseLike'. -!!! error TS2345: Type 'IPromise' is not assignable to type 'PromiseLike'. -!!! error TS2345: Types of property 'then' are incompatible. -!!! error TS2345: Type '(success?: (value: number) => IPromise) => IPromise' is not assignable to type '(onfulfilled?: (value: number) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => PromiseLike'. -!!! error TS2345: Types of parameters 'success' and 'onfulfilled' are incompatible. -!!! error TS2345: Type 'TResult1 | PromiseLike' is not assignable to type 'IPromise'. -!!! error TS2345: Type 'TResult1' is not assignable to type 'IPromise'. + ~~~~~~~~~~ +!!! error TS2322: Type 'IPromise' is not assignable to type 'number | PromiseLike'. +!!! error TS2322: Type 'IPromise' is not assignable to type 'PromiseLike'. +!!! error TS2322: Types of property 'then' are incompatible. +!!! error TS2322: Type '(success?: (value: number) => IPromise) => IPromise' is not assignable to type '(onfulfilled?: (value: number) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => PromiseLike'. +!!! error TS2322: Types of parameters 'success' and 'onfulfilled' are incompatible. +!!! error TS2322: Type 'TResult1 | PromiseLike' is not assignable to type 'IPromise'. +!!! error TS2322: Type 'TResult1' is not assignable to type 'IPromise'. +!!! related TS6502 /.ts/lib.es5.d.ts:1336:57: The expected type comes from the return type of this signature. \ No newline at end of file diff --git a/tests/baselines/reference/targetTypeTest3.errors.txt b/tests/baselines/reference/targetTypeTest3.errors.txt index f5dab732ed3..40d24da28d1 100644 --- a/tests/baselines/reference/targetTypeTest3.errors.txt +++ b/tests/baselines/reference/targetTypeTest3.errors.txt @@ -1,17 +1,16 @@ -tests/cases/compiler/targetTypeTest3.ts(4,5): error TS2322: Type '(string | number)[]' is not assignable to type 'string[]'. - Type 'string | number' is not assignable to type 'string'. - Type 'number' is not assignable to type 'string'. +tests/cases/compiler/targetTypeTest3.ts(4,21): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/compiler/targetTypeTest3.ts(4,23): error TS2322: Type 'number' is not assignable to type 'string'. -==== tests/cases/compiler/targetTypeTest3.ts (1 errors) ==== +==== tests/cases/compiler/targetTypeTest3.ts (2 errors) ==== // Test target typing for array literals and call expressions var a : string[] = [1,2,"3"]; // should produce an error - ~ -!!! error TS2322: Type '(string | number)[]' is not assignable to type 'string[]'. -!!! error TS2322: Type 'string | number' is not assignable to type 'string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. function func1(stuff:any[]) { return stuff; } diff --git a/tests/baselines/reference/trailingCommaInHeterogenousArrayLiteral1.errors.txt b/tests/baselines/reference/trailingCommaInHeterogenousArrayLiteral1.errors.txt index 32c1a470bc3..6335da5bfd1 100644 --- a/tests/baselines/reference/trailingCommaInHeterogenousArrayLiteral1.errors.txt +++ b/tests/baselines/reference/trailingCommaInHeterogenousArrayLiteral1.errors.txt @@ -1,7 +1,5 @@ -tests/cases/compiler/trailingCommaInHeterogenousArrayLiteral1.ts(5,19): error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. -tests/cases/compiler/trailingCommaInHeterogenousArrayLiteral1.ts(6,19): error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. +tests/cases/compiler/trailingCommaInHeterogenousArrayLiteral1.ts(5,26): error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/trailingCommaInHeterogenousArrayLiteral1.ts(6,26): error TS2322: Type 'string' is not assignable to type 'number'. ==== tests/cases/compiler/trailingCommaInHeterogenousArrayLiteral1.ts (2 errors) ==== @@ -10,13 +8,11 @@ tests/cases/compiler/trailingCommaInHeterogenousArrayLiteral1.ts(6,19): error TS callTest() { // these two should give the same error this.test([1, 2, "hi", 5, ]); - ~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. -!!! error TS2345: Type 'string | number' is not assignable to type 'number'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. + ~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. this.test([1, 2, "hi", 5]); - ~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'. + ~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. } } \ No newline at end of file diff --git a/tests/baselines/reference/tsxTypeArgumentPartialDefinitionStillErrors.errors.txt b/tests/baselines/reference/tsxTypeArgumentPartialDefinitionStillErrors.errors.txt index 255d0eb32bc..565485f03b7 100644 --- a/tests/baselines/reference/tsxTypeArgumentPartialDefinitionStillErrors.errors.txt +++ b/tests/baselines/reference/tsxTypeArgumentPartialDefinitionStillErrors.errors.txt @@ -15,5 +15,4 @@ tests/cases/compiler/file.tsx(11,14): error TS2322: Type 'number' is not assigna prop={1}>; // should error ~~~~ !!! error TS2322: Type 'number' is not assignable to type 'string'. -!!! related TS6500 /.ts/lib.es5.d.ts:1382:39: The expected type comes from property 'prop' which is declared here on type 'Record' \ No newline at end of file diff --git a/tests/baselines/reference/typeArgumentInferenceWithConstraints.errors.txt b/tests/baselines/reference/typeArgumentInferenceWithConstraints.errors.txt index 9888c8558f1..3b7750f23f0 100644 --- a/tests/baselines/reference/typeArgumentInferenceWithConstraints.errors.txt +++ b/tests/baselines/reference/typeArgumentInferenceWithConstraints.errors.txt @@ -1,8 +1,7 @@ tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(11,17): error TS2344: Type '{}' does not satisfy the constraint 'number'. tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(16,23): error TS2344: Type 'number' does not satisfy the constraint 'string'. tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(17,23): error TS2344: Type '{}' does not satisfy the constraint 'number'. -tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(33,15): error TS2345: Argument of type '() => string' is not assignable to parameter of type '() => Window'. - Type 'string' is not assignable to type 'Window'. +tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(33,21): error TS2322: Type 'string' is not assignable to type 'Window'. tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(35,15): error TS2344: Type 'number' does not satisfy the constraint 'Window'. tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(41,35): error TS2345: Argument of type '(x: string) => string' is not assignable to parameter of type '(x: number) => void'. Types of parameters 'x' and 'x' are incompatible. @@ -61,9 +60,9 @@ tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConst // Generic call with argument of function type whose parameter is not of type parameter type but body/return type uses type parameter function someGenerics3(producer: () => T) { } someGenerics3(() => ''); // Error - ~~~~~~~~ -!!! error TS2345: Argument of type '() => string' is not assignable to parameter of type '() => Window'. -!!! error TS2345: Type 'string' is not assignable to type 'Window'. + ~~ +!!! error TS2322: Type 'string' is not assignable to type 'Window'. +!!! related TS6502 tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts:32:52: The expected type comes from the return type of this signature. someGenerics3(() => undefined); someGenerics3(() => 3); // Error ~~~~~~ diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.errors.txt b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.errors.txt index 5a6047222ee..e2551020f84 100644 --- a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.errors.txt +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.errors.txt @@ -1,6 +1,5 @@ -tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts(7,25): error TS2345: Argument of type '(x: A) => A' is not assignable to parameter of type '(x: A) => B'. - Type 'A' is not assignable to type 'B'. - Property 'b' is missing in type 'A'. +tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts(7,30): error TS2322: Type 'A' is not assignable to type 'B'. + Property 'b' is missing in type 'A'. ==== tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts (1 errors) ==== @@ -11,7 +10,7 @@ tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts(7,25): var a: A, b: B; var d = f(a, b, x => x, x => x); // A => A not assignable to A => B - ~~~~~~ -!!! error TS2345: Argument of type '(x: A) => A' is not assignable to parameter of type '(x: A) => B'. -!!! error TS2345: Type 'A' is not assignable to type 'B'. -!!! error TS2345: Property 'b' is missing in type 'A'. \ No newline at end of file + ~ +!!! error TS2322: Type 'A' is not assignable to type 'B'. +!!! error TS2322: Property 'b' is missing in type 'A'. +!!! related TS6502 tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts:1:51: The expected type comes from the return type of this signature. \ No newline at end of file diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.errors.txt b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.errors.txt index cd0801f7ba9..d678fb7f908 100644 --- a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.errors.txt +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.errors.txt @@ -1,6 +1,5 @@ -tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts(7,29): error TS2345: Argument of type '(t2: A) => A' is not assignable to parameter of type '(t2: A) => B'. - Type 'A' is not assignable to type 'B'. - Property 'b' is missing in type 'A'. +tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts(7,35): error TS2322: Type 'A' is not assignable to type 'B'. + Property 'b' is missing in type 'A'. ==== tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts (1 errors) ==== @@ -11,7 +10,7 @@ tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts(7,29): var a: A, b: B; var d = f(a, b, u2 => u2.b, t2 => t2); - ~~~~~~~~ -!!! error TS2345: Argument of type '(t2: A) => A' is not assignable to parameter of type '(t2: A) => B'. -!!! error TS2345: Type 'A' is not assignable to type 'B'. -!!! error TS2345: Property 'b' is missing in type 'A'. \ No newline at end of file + ~~ +!!! error TS2322: Type 'A' is not assignable to type 'B'. +!!! error TS2322: Property 'b' is missing in type 'A'. +!!! related TS6502 tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts:1:56: The expected type comes from the return type of this signature. \ No newline at end of file diff --git a/tests/baselines/reference/widenedTypes.errors.txt b/tests/baselines/reference/widenedTypes.errors.txt index aac9627adeb..fb6779ff0eb 100644 --- a/tests/baselines/reference/widenedTypes.errors.txt +++ b/tests/baselines/reference/widenedTypes.errors.txt @@ -5,8 +5,7 @@ tests/cases/compiler/widenedTypes.ts(7,15): error TS2531: Object is possibly 'nu tests/cases/compiler/widenedTypes.ts(9,14): error TS2695: Left side of comma operator is unused and has no side effects. tests/cases/compiler/widenedTypes.ts(10,1): error TS2322: Type '""' is not assignable to type 'number'. tests/cases/compiler/widenedTypes.ts(17,1): error TS2322: Type '""' is not assignable to type 'number'. -tests/cases/compiler/widenedTypes.ts(22,5): error TS2322: Type 'number[]' is not assignable to type 'string[]'. - Type 'number' is not assignable to type 'string'. +tests/cases/compiler/widenedTypes.ts(22,22): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/compiler/widenedTypes.ts(23,39): error TS2322: Type 'number' is not assignable to type 'string'. @@ -47,9 +46,8 @@ tests/cases/compiler/widenedTypes.ts(23,39): error TS2322: Type 'number' is not // Highlights the difference between array literals and object literals var arr: string[] = [3, null]; // not assignable because null is not widened. BCT is {} - ~~~ -!!! error TS2322: Type 'number[]' is not assignable to type 'string[]'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. var obj: { [x: string]: string; } = { x: 3, y: null }; // assignable because null is widened, and therefore BCT is any ~ !!! error TS2322: Type 'number' is not assignable to type 'string'. diff --git a/tests/baselines/reference/wrappedAndRecursiveConstraints4.errors.txt b/tests/baselines/reference/wrappedAndRecursiveConstraints4.errors.txt index 65bfc5b20d5..4b19087eea0 100644 --- a/tests/baselines/reference/wrappedAndRecursiveConstraints4.errors.txt +++ b/tests/baselines/reference/wrappedAndRecursiveConstraints4.errors.txt @@ -18,5 +18,4 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/wrappedAndRecursi var r2 = r({ length: 3, charAt: (x: number) => { '' } }); // error ~~~~~~ !!! error TS2322: Type '(x: number) => void' is not assignable to type '(pos: number) => string'. -!!! error TS2322: Type 'void' is not assignable to type 'string'. -!!! related TS6500 /.ts/lib.es5.d.ts:332:5: The expected type comes from property 'charAt' which is declared here on type 'string' \ No newline at end of file +!!! error TS2322: Type 'void' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts b/tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts new file mode 100644 index 00000000000..283c9424388 --- /dev/null +++ b/tests/cases/compiler/deepElaborationsIntoArrowExpressions.ts @@ -0,0 +1,19 @@ +// @target: es6 +const a: { + y(): "a" +} = { + y: () => "b" +}; + +interface Foo { + a: number; +} + +function foo1(): () => Foo { + return () => ({a: ''}); +} + +function foo3(): Foo[] { + return [{a: ''}]; +} +var y: Foo[] = [{a: ''}] \ No newline at end of file From e7cf9994ce0f4456016cf18ed96323459ef11e69 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 17 Sep 2018 18:02:59 -0700 Subject: [PATCH 41/47] Implement readDirectory on the watch mode CompilerHost --- src/compiler/watch.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index b914eb329b4..e65d0d49b86 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -546,7 +546,8 @@ namespace ts { }, maxNumberOfFilesToIterateForInvalidation: host.maxNumberOfFilesToIterateForInvalidation, getCurrentProgram, - writeLog + writeLog, + readDirectory: (path, extensions, exclude, include, depth?) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth), }; // Cache for the module resolution const resolutionCache = createResolutionCache(compilerHost, configFileName ? From c510df1a53b4b549f3c343092e9be132f5bc025f Mon Sep 17 00:00:00 2001 From: Alexander T Date: Tue, 18 Sep 2018 12:17:21 +0300 Subject: [PATCH 42/47] deny using allowJs option with composite --- src/compiler/program.ts | 4 ++-- ...ationWithEnabledCompositeOption.errors.txt | 12 ++++++++++ ...leCompilationWithEnabledCompositeOption.js | 24 +++++++++++++++++++ ...pilationWithEnabledCompositeOption.symbols | 10 ++++++++ ...ompilationWithEnabledCompositeOption.types | 10 ++++++++ ...leCompilationWithEnabledCompositeOption.ts | 10 ++++++++ 6 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.errors.txt create mode 100644 tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.js create mode 100644 tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.symbols create mode 100644 tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.types create mode 100644 tests/cases/compiler/jsFileCompilationWithEnabledCompositeOption.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c7599e9bd6b..8b5d4b6a6e7 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2609,8 +2609,8 @@ namespace ts { } } - if (!options.noEmit && options.allowJs && options.declaration) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"); + if (!options.noEmit && options.allowJs && (options.declaration || options.composite)) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", options.declaration ? "declaration" : "composite"); } if (options.checkJs && !options.allowJs) { diff --git a/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.errors.txt b/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.errors.txt new file mode 100644 index 00000000000..7133188adc0 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.errors.txt @@ -0,0 +1,12 @@ +error TS5053: Option 'allowJs' cannot be specified with option 'composite'. + + +!!! error TS5053: Option 'allowJs' cannot be specified with option 'composite'. +==== tests/cases/compiler/a.ts (0 errors) ==== + class c { + } + +==== tests/cases/compiler/b.js (0 errors) ==== + function foo() { + } + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.js b/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.js new file mode 100644 index 00000000000..e34edb10ff4 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.js @@ -0,0 +1,24 @@ +//// [tests/cases/compiler/jsFileCompilationWithEnabledCompositeOption.ts] //// + +//// [a.ts] +class c { +} + +//// [b.js] +function foo() { +} + + +//// [out.js] +var c = /** @class */ (function () { + function c() { + } + return c; +}()); +function foo() { +} + + +//// [out.d.ts] +declare class c { +} diff --git a/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.symbols b/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.symbols new file mode 100644 index 00000000000..5260b8d6cf3 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/a.ts === +class c { +>c : Symbol(c, Decl(a.ts, 0, 0)) +} + +=== tests/cases/compiler/b.js === +function foo() { +>foo : Symbol(foo, Decl(b.js, 0, 0)) +} + diff --git a/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.types b/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.types new file mode 100644 index 00000000000..dce83eeb8eb --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationWithEnabledCompositeOption.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/a.ts === +class c { +>c : c +} + +=== tests/cases/compiler/b.js === +function foo() { +>foo : () => void +} + diff --git a/tests/cases/compiler/jsFileCompilationWithEnabledCompositeOption.ts b/tests/cases/compiler/jsFileCompilationWithEnabledCompositeOption.ts new file mode 100644 index 00000000000..90340ef5d3a --- /dev/null +++ b/tests/cases/compiler/jsFileCompilationWithEnabledCompositeOption.ts @@ -0,0 +1,10 @@ +// @allowJs: true +// @out: out.js +// @composite: true +// @filename: a.ts +class c { +} + +// @filename: b.js +function foo() { +} From d11117829d09bde9db4027dbdad35c8967362870 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Tue, 18 Sep 2018 11:33:56 +0300 Subject: [PATCH 43/47] allow using declarationDir with composite option --- src/compiler/program.ts | 2 +- ...onEmitToDeclarationDirWithCompositeOption.js | 17 +++++++++++++++++ ...tToDeclarationDirWithCompositeOption.symbols | 10 ++++++++++ ...mitToDeclarationDirWithCompositeOption.types | 8 ++++++++ ...EmitToDeclarationDirWithDeclarationOption.js | 17 +++++++++++++++++ ...oDeclarationDirWithDeclarationOption.symbols | 10 ++++++++++ ...tToDeclarationDirWithDeclarationOption.types | 8 ++++++++ ...outCompositeAndDeclarationOptions.errors.txt | 16 ++++++++++++++++ ...nDirWithoutCompositeAndDeclarationOptions.js | 10 ++++++++++ ...ithoutCompositeAndDeclarationOptions.symbols | 10 ++++++++++ ...rWithoutCompositeAndDeclarationOptions.types | 8 ++++++++ ...onEmitToDeclarationDirWithCompositeOption.ts | 11 +++++++++++ ...EmitToDeclarationDirWithDeclarationOption.ts | 11 +++++++++++ ...nDirWithoutCompositeAndDeclarationOptions.ts | 10 ++++++++++ 14 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.js create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.symbols create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.types create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.js create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.symbols create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.types create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.errors.txt create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.js create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.symbols create mode 100644 tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.types create mode 100644 tests/cases/compiler/declarationEmitToDeclarationDirWithCompositeOption.ts create mode 100644 tests/cases/compiler/declarationEmitToDeclarationDirWithDeclarationOption.ts create mode 100644 tests/cases/compiler/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c7599e9bd6b..75e111ace4c 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2532,7 +2532,7 @@ namespace ts { } if (options.declarationDir) { - if (!options.declaration) { + if (!getEmitDeclarations(options)) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration"); } if (options.out || options.outFile) { diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.js b/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.js new file mode 100644 index 00000000000..f048e6aceea --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.js @@ -0,0 +1,17 @@ +//// [test.ts] +interface Foo { + x: number; +} +export default Foo; + + +//// [test.js] +"use strict"; +exports.__esModule = true; + + +//// [test.d.ts] +interface Foo { + x: number; +} +export default Foo; diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.symbols b/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.symbols new file mode 100644 index 00000000000..74f9fba394b --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.symbols @@ -0,0 +1,10 @@ +=== /foo/test.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(test.ts, 0, 0)) + + x: number; +>x : Symbol(Foo.x, Decl(test.ts, 0, 15)) +} +export default Foo; +>Foo : Symbol(Foo, Decl(test.ts, 0, 0)) + diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.types b/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.types new file mode 100644 index 00000000000..489a84bb9f1 --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithCompositeOption.types @@ -0,0 +1,8 @@ +=== /foo/test.ts === +interface Foo { + x: number; +>x : number +} +export default Foo; +>Foo : Foo + diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.js b/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.js new file mode 100644 index 00000000000..f048e6aceea --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.js @@ -0,0 +1,17 @@ +//// [test.ts] +interface Foo { + x: number; +} +export default Foo; + + +//// [test.js] +"use strict"; +exports.__esModule = true; + + +//// [test.d.ts] +interface Foo { + x: number; +} +export default Foo; diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.symbols b/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.symbols new file mode 100644 index 00000000000..74f9fba394b --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.symbols @@ -0,0 +1,10 @@ +=== /foo/test.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(test.ts, 0, 0)) + + x: number; +>x : Symbol(Foo.x, Decl(test.ts, 0, 15)) +} +export default Foo; +>Foo : Symbol(Foo, Decl(test.ts, 0, 0)) + diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.types b/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.types new file mode 100644 index 00000000000..489a84bb9f1 --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.types @@ -0,0 +1,8 @@ +=== /foo/test.ts === +interface Foo { + x: number; +>x : number +} +export default Foo; +>Foo : Foo + diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.errors.txt b/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.errors.txt new file mode 100644 index 00000000000..e2a5a20452c --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.errors.txt @@ -0,0 +1,16 @@ +/foo/tsconfig.json(2,26): error TS5052: Option 'declarationDir' cannot be specified without specifying option 'declaration'. + + +==== /foo/tsconfig.json (1 errors) ==== + { + "compilerOptions": { "declarationDir": "out" } + ~~~~~~~~~~~~~~~~ +!!! error TS5052: Option 'declarationDir' cannot be specified without specifying option 'declaration'. + } + +==== /foo/test.ts (0 errors) ==== + interface Foo { + x: number; + } + export default Foo; + \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.js b/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.js new file mode 100644 index 00000000000..48235293467 --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.js @@ -0,0 +1,10 @@ +//// [test.ts] +interface Foo { + x: number; +} +export default Foo; + + +//// [test.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.symbols b/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.symbols new file mode 100644 index 00000000000..74f9fba394b --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.symbols @@ -0,0 +1,10 @@ +=== /foo/test.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(test.ts, 0, 0)) + + x: number; +>x : Symbol(Foo.x, Decl(test.ts, 0, 15)) +} +export default Foo; +>Foo : Symbol(Foo, Decl(test.ts, 0, 0)) + diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.types b/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.types new file mode 100644 index 00000000000..489a84bb9f1 --- /dev/null +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.types @@ -0,0 +1,8 @@ +=== /foo/test.ts === +interface Foo { + x: number; +>x : number +} +export default Foo; +>Foo : Foo + diff --git a/tests/cases/compiler/declarationEmitToDeclarationDirWithCompositeOption.ts b/tests/cases/compiler/declarationEmitToDeclarationDirWithCompositeOption.ts new file mode 100644 index 00000000000..77a4c3099cf --- /dev/null +++ b/tests/cases/compiler/declarationEmitToDeclarationDirWithCompositeOption.ts @@ -0,0 +1,11 @@ +// @composite: true +// @filename: /foo/tsconfig.json +{ + "compilerOptions": { "composite": true, "declarationDir": "out" } +} + +// @filename: /foo/test.ts +interface Foo { + x: number; +} +export default Foo; diff --git a/tests/cases/compiler/declarationEmitToDeclarationDirWithDeclarationOption.ts b/tests/cases/compiler/declarationEmitToDeclarationDirWithDeclarationOption.ts new file mode 100644 index 00000000000..e3d4231a8f6 --- /dev/null +++ b/tests/cases/compiler/declarationEmitToDeclarationDirWithDeclarationOption.ts @@ -0,0 +1,11 @@ +// @declaration: true +// @filename: /foo/tsconfig.json +{ + "compilerOptions": { "declaration": true, "declarationDir": "out" } +} + +// @filename: /foo/test.ts +interface Foo { + x: number; +} +export default Foo; diff --git a/tests/cases/compiler/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.ts b/tests/cases/compiler/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.ts new file mode 100644 index 00000000000..08405e5fc96 --- /dev/null +++ b/tests/cases/compiler/declarationEmitToDeclarationDirWithoutCompositeAndDeclarationOptions.ts @@ -0,0 +1,10 @@ +// @filename: /foo/tsconfig.json +{ + "compilerOptions": { "declarationDir": "out" } +} + +// @filename: /foo/test.ts +interface Foo { + x: number; +} +export default Foo; From 5b5af23b4196364a66a00eff58be8e57d92d8477 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Tue, 18 Sep 2018 14:46:42 +0300 Subject: [PATCH 44/47] use getEmitDeclarations helper --- src/compiler/program.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 8b5d4b6a6e7..d8c852c996b 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2609,7 +2609,7 @@ namespace ts { } } - if (!options.noEmit && options.allowJs && (options.declaration || options.composite)) { + if (!options.noEmit && options.allowJs && getEmitDeclarations(options)) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", options.declaration ? "declaration" : "composite"); } From b484370dcc2c4d65625974ff27413976799ddb8b Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Tue, 18 Sep 2018 09:34:08 -0700 Subject: [PATCH 45/47] Clean up for type precision and clarity --- .../codefixes/convertToAsyncFunction.ts | 20 +++++++++++-------- .../unittests/convertToAsyncFunction.ts | 6 ++++++ .../convertToAsyncFunction_NoCatch.js | 15 ++++++++++++++ .../convertToAsyncFunction_NoCatch.ts | 15 ++++++++++++++ 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.ts diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 9998569b585..01aaaae65ca 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -372,7 +372,7 @@ namespace ts.codefix { // the identifier is empty when the handler (.then()) ignores the argument - In this situation we do not need to save the result of the promise returning call const originalNodeParent = node.original ? node.original.parent : node.parent; if (prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { - return createTransformedStatement(prevArgName, createAwait(node), transformer).concat(); // hack to make the types match + return createTransformedStatement(prevArgName, createAwait(node), transformer); } else if (!prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { return [createStatement(createAwait(node))]; @@ -381,7 +381,7 @@ namespace ts.codefix { return [createReturn(getSynthesizedDeepClone(node))]; } - function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): NodeArray { + function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): MutableNodeArray { if (!prevArgName || prevArgName.identifier.text.length === 0) { // if there's no argName to assign to, there still might be side effects return createNodeArray([createStatement(rightHandSide)]); @@ -405,7 +405,10 @@ namespace ts.codefix { // do not produce a transformed statement for a null argument break; case SyntaxKind.Identifier: // identifier includes undefined - if (!argName) break; + if (!argName) { + // undefined was argument passed to promise handler + break; + } const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, argName ? [argName.identifier] : []); if (shouldReturn) { @@ -533,7 +536,7 @@ namespace ts.codefix { return innerCbBody; } - function getArgName(funcNode: Node, transformer: Transformer): SynthIdentifier | undefined { + function getArgName(funcNode: Expression, transformer: Transformer): SynthIdentifier | undefined { const numberOfAssignmentsOriginal = 0; const types: Type[] = []; @@ -543,20 +546,21 @@ namespace ts.codefix { if (isFunctionLikeDeclaration(funcNode)) { if (funcNode.parameters.length > 0) { const param = funcNode.parameters[0].name as Identifier; - name = getMapEntryIfExists(param); + name = getMapEntryOrDefault(param); } } else if (isIdentifier(funcNode)) { - name = getMapEntryIfExists(funcNode); + name = getMapEntryOrDefault(funcNode); } - if (!name || name.identifier === undefined || name.identifier.text === "undefined") { + // return undefined argName when arg is null or undefined + if (!name || name.identifier.text === "undefined") { return undefined; } return name; - function getMapEntryIfExists(identifier: Identifier): SynthIdentifier { + function getMapEntryOrDefault(identifier: Identifier): SynthIdentifier { const originalNode = getOriginalNode(identifier); const symbol = getSymbol(originalNode); diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index 5eb49eaa445..fe2d99e1961 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -487,6 +487,12 @@ function [#|f|]():Promise { function [#|f|]() { return fetch('https://typescriptlang.org').then(undefined, rejection => console.log("rejected:", rejection)); } +` + ); + _testConvertToAsyncFunction("convertToAsyncFunction_NoCatch", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined); +} ` ); _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestion", ` diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.js new file mode 100644 index 00000000000..25061a4dfb5 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.js @@ -0,0 +1,15 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + try { + const x = await fetch('https://typescriptlang.org'); + return x.statusText; + } + catch (e) { } +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.ts new file mode 100644 index 00000000000..25061a4dfb5 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.ts @@ -0,0 +1,15 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + try { + const x = await fetch('https://typescriptlang.org'); + return x.statusText; + } + catch (e) { } +} From b850b3b88fe3fcc16c8c9a4aab3fcb789dcc0095 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Tue, 18 Sep 2018 10:26:12 -0700 Subject: [PATCH 46/47] Update test name --- src/testRunner/unittests/convertToAsyncFunction.ts | 2 +- ...tion_NoCatch.js => convertToAsyncFunction_NoCatchHandler.js} | 0 ...tion_NoCatch.ts => convertToAsyncFunction_NoCatchHandler.ts} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename tests/baselines/reference/convertToAsyncFunction/{convertToAsyncFunction_NoCatch.js => convertToAsyncFunction_NoCatchHandler.js} (100%) rename tests/baselines/reference/convertToAsyncFunction/{convertToAsyncFunction_NoCatch.ts => convertToAsyncFunction_NoCatchHandler.ts} (100%) diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index fe2d99e1961..88ea3d04aae 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -489,7 +489,7 @@ function [#|f|]() { } ` ); - _testConvertToAsyncFunction("convertToAsyncFunction_NoCatch", ` + _testConvertToAsyncFunction("convertToAsyncFunction_NoCatchHandler", ` function [#|f|]() { return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined); } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatchHandler.js similarity index 100% rename from tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.js rename to tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatchHandler.js diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatchHandler.ts similarity index 100% rename from tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatch.ts rename to tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoCatchHandler.ts From c57ff087d6b72f1ef5ffe54ab5c1b2710481bb94 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 18 Sep 2018 11:47:29 -0700 Subject: [PATCH 47/47] Add codefix to generate types for untyped module (#26588) --- package.json | 1 + src/compiler/core.ts | 10 +- src/compiler/diagnosticMessages.json | 10 +- src/compiler/factory.ts | 2 +- src/compiler/inspectValue.ts | 159 +++++ src/compiler/moduleNameResolver.ts | 13 +- src/compiler/tsconfig.json | 3 +- src/harness/fourslash.ts | 33 +- src/jsTyping/shared.ts | 1 + src/jsTyping/types.ts | 19 +- src/server/project.ts | 9 + src/server/session.ts | 4 +- src/server/typingsCache.ts | 7 + src/services/codefixes/fixCannotFindModule.ts | 144 +++- src/services/codefixes/generateTypes.ts | 227 ++++++ src/services/services.ts | 31 +- src/services/textChanges.ts | 56 +- src/services/tsconfig.json | 3 +- src/services/types.ts | 51 +- .../unittests/convertToAsyncFunction.ts | 2 +- .../unittests/extractTestHelpers.ts | 25 +- src/testRunner/unittests/organizeImports.ts | 4 +- src/testRunner/unittests/textChanges.ts | 2 +- .../unittests/tsserverProjectSystem.ts | 3 +- src/tsserver/server.ts | 22 +- src/typingsInstaller/nodeTypingsInstaller.ts | 5 + .../reference/api/tsserverlibrary.d.ts | 20 +- tests/baselines/reference/api/typescript.d.ts | 19 +- .../reference/generateTypes/global.d.ts | 236 +++++++ .../reference/generateTypes/lodash.d.ts | 668 ++++++++++++++++++ .../fourslash/codeFixCannotFindModule_all.ts | 5 +- .../codeFixCannotFindModule_generateTypes.ts | 44 ++ ...deFixCannotFindModule_generateTypes_all.ts | 47 ++ ...generateTypes_noExistingCompilerOptions.ts | 28 + ..._generateTypes_notForNonexistentPackage.ts | 13 + ...dule_generateTypes_typesDirectoryExists.ts | 30 + .../fourslash/codeFixGenerateDefinitions.ts | 9 + .../codeFixUndeclaredMethodFunctionArgs.ts | 2 +- tests/cases/fourslash/formatWithTabs.ts | 2 +- tests/cases/fourslash/fourslash.ts | 11 +- tests/cases/fourslash/generateTypes.ts | 109 +++ .../fourslash/generateTypes_baselines.ts | 35 + .../cases/fourslash/generateTypes_classes.ts | 109 +++ 43 files changed, 2117 insertions(+), 116 deletions(-) create mode 100644 src/compiler/inspectValue.ts create mode 100644 src/services/codefixes/generateTypes.ts create mode 100644 tests/baselines/reference/generateTypes/global.d.ts create mode 100644 tests/baselines/reference/generateTypes/lodash.d.ts create mode 100644 tests/cases/fourslash/codeFixCannotFindModule_generateTypes.ts create mode 100644 tests/cases/fourslash/codeFixCannotFindModule_generateTypes_all.ts create mode 100644 tests/cases/fourslash/codeFixCannotFindModule_generateTypes_noExistingCompilerOptions.ts create mode 100644 tests/cases/fourslash/codeFixCannotFindModule_generateTypes_notForNonexistentPackage.ts create mode 100644 tests/cases/fourslash/codeFixCannotFindModule_generateTypes_typesDirectoryExists.ts create mode 100644 tests/cases/fourslash/codeFixGenerateDefinitions.ts create mode 100644 tests/cases/fourslash/generateTypes.ts create mode 100644 tests/cases/fourslash/generateTypes_baselines.ts create mode 100644 tests/cases/fourslash/generateTypes_classes.ts diff --git a/package.json b/package.json index 55acc40268d..159788e697f 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "gulp-typescript": "latest", "istanbul": "latest", "jake": "latest", + "lodash": "4.17.10", "merge2": "latest", "minimist": "latest", "mkdirp": "latest", diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 45b9351759c..22fc19bcc8a 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1409,9 +1409,12 @@ namespace ts { /** * Tests whether a value is string */ - export function isString(text: any): text is string { + export function isString(text: unknown): text is string { return typeof text === "string"; } + export function isNumber(x: unknown): x is number { + return typeof x === "number"; + } export function tryCast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut | undefined; export function tryCast(value: T, test: (value: T) => boolean): T | undefined; @@ -1534,6 +1537,7 @@ namespace ts { * Every function should be assignable to this, but this should not be assignable to every function. */ export type AnyFunction = (...args: never[]) => void; + export type AnyConstructor = new (...args: unknown[]) => unknown; export namespace Debug { export let currentAssertionLevel = AssertionLevel.None; @@ -2125,4 +2129,8 @@ namespace ts { deleted(oldItems[oldIndex++]); } } + + export function fill(length: number, cb: (index: number) => T): T[] { + return new Array(length).fill(0).map((_, i) => cb(i)); + } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index eb83d48ae75..706a3552765 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4671,5 +4671,13 @@ "Convert all to async functions": { "category": "Message", "code": 95066 + }, + "Generate types for '{0}'": { + "category": "Message", + "code": 95067 + }, + "Generate types for all packages without types": { + "category": "Message", + "code": 95068 } -} +} \ No newline at end of file diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 984e6d59b2e..4b2855790a9 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -235,7 +235,7 @@ namespace ts { // Modifiers - export function createModifier(kind: T) { + export function createModifier(kind: T): Token { return createToken(kind); } diff --git a/src/compiler/inspectValue.ts b/src/compiler/inspectValue.ts new file mode 100644 index 00000000000..86b45b65031 --- /dev/null +++ b/src/compiler/inspectValue.ts @@ -0,0 +1,159 @@ +/* @internal */ +namespace ts { + export interface InspectValueOptions { + readonly fileNameToRequire: string; + } + + export const enum ValueKind { Const, Array, FunctionOrClass, Object } + export interface ValueInfoBase { + readonly name: string; + } + export type ValueInfo = ValueInfoSimple | ValueInfoArray | ValueInfoFunctionOrClass | ValueInfoObject; + export interface ValueInfoSimple extends ValueInfoBase { + readonly kind: ValueKind.Const; + readonly typeName: string; + readonly comment?: string | undefined; + } + export interface ValueInfoFunctionOrClass extends ValueInfoBase { + readonly kind: ValueKind.FunctionOrClass; + readonly source: string | number; // For a native function, this is the length. + readonly prototypeMembers: ReadonlyArray; + readonly namespaceMembers: ReadonlyArray; + } + export interface ValueInfoArray extends ValueInfoBase { + readonly kind: ValueKind.Array; + readonly inner: ValueInfo; + } + export interface ValueInfoObject extends ValueInfoBase { + readonly kind: ValueKind.Object; + readonly members: ReadonlyArray; + } + + export function inspectModule(fileNameToRequire: string): ValueInfo { + return inspectValue(removeFileExtension(getBaseFileName(fileNameToRequire)), tryRequire(fileNameToRequire)); + } + + export function inspectValue(name: string, value: unknown): ValueInfo { + return getValueInfo(name, value, getRecurser()); + } + + type Recurser = (obj: unknown, name: string, cbOk: () => T, cbFail: (isCircularReference: boolean, keyStack: ReadonlyArray) => T) => T; + function getRecurser(): Recurser { + const seen = new Set(); + const nameStack: string[] = []; + return (obj, name, cbOk, cbFail) => { + if (seen.has(obj) || nameStack.length > 4) { + return cbFail(seen.has(obj), nameStack); + } + + seen.add(obj); + nameStack.push(name); + const res = cbOk(); + nameStack.pop(); + seen.delete(obj); + return res; + }; + } + + function getValueInfo(name: string, value: unknown, recurser: Recurser): ValueInfo { + return recurser(value, name, + (): ValueInfo => { + if (typeof value === "function") return getFunctionOrClassInfo(value as AnyFunction, name, recurser); + if (typeof value === "object") { + const builtin = getBuiltinType(name, value as object, recurser); + if (builtin !== undefined) return builtin; + const entries = getEntriesOfObject(value as object); + return { kind: ValueKind.Object, name, members: flatMap(entries, ({ key, value }) => getValueInfo(key, value, recurser)) }; + } + return { kind: ValueKind.Const, name, typeName: isNullOrUndefined(value) ? "any" : typeof value }; + }, + (isCircularReference, keyStack) => anyValue(name, ` ${isCircularReference ? "Circular reference" : "Too-deep object hierarchy"} from ${keyStack.join(".")}`)); + } + + function getFunctionOrClassInfo(fn: AnyFunction, name: string, recurser: Recurser): ValueInfoFunctionOrClass { + const prototypeMembers = getPrototypeMembers(fn, recurser); + const namespaceMembers = flatMap(getEntriesOfObject(fn), ({ key, value }) => getValueInfo(key, value, recurser)); + const toString = cast(Function.prototype.toString.call(fn), isString); + const source = stringContains(toString, "{ [native code] }") ? getFunctionLength(fn) : toString; + return { kind: ValueKind.FunctionOrClass, name, source, namespaceMembers, prototypeMembers }; + } + + const builtins: () => ReadonlyMap = memoize(() => { + const map = createMap(); + for (const { key, value } of getEntriesOfObject(global)) { + if (typeof value === "function" && typeof value.prototype === "object" && value !== Object) { + map.set(key, value as AnyConstructor); + } + } + return map; + }); + function getBuiltinType(name: string, value: object, recurser: Recurser): ValueInfo | undefined { + return isArray(value) + ? { name, kind: ValueKind.Array, inner: value.length && getValueInfo("element", first(value), recurser) || anyValue(name) } + : forEachEntry(builtins(), (builtin, builtinName): ValueInfo | undefined => + value instanceof builtin ? { kind: ValueKind.Const, name, typeName: builtinName } : undefined); + } + + function getPrototypeMembers(fn: AnyFunction, recurser: Recurser): ReadonlyArray { + const prototype = fn.prototype as unknown; + // tslint:disable-next-line no-unnecessary-type-assertion (TODO: update LKG and it will really be unnecessary) + return typeof prototype !== "object" || prototype === null ? emptyArray : mapDefined(getEntriesOfObject(prototype as object), ({ key, value }) => + key === "constructor" ? undefined : getValueInfo(key, value, recurser)); + } + + const ignoredProperties: ReadonlySet = new Set(["arguments", "caller", "constructor", "eval", "super_"]); + const reservedFunctionProperties: ReadonlySet = new Set(Object.getOwnPropertyNames(noop)); + interface ObjectEntry { readonly key: string; readonly value: unknown; } + function getEntriesOfObject(obj: object): ReadonlyArray { + const seen = createMap(); + const entries: ObjectEntry[] = []; + let chain = obj; + while (!isNullOrUndefined(chain) && chain !== Object.prototype && chain !== Function.prototype) { + for (const key of Object.getOwnPropertyNames(chain)) { + if (!isJsPrivate(key) && + !ignoredProperties.has(key) && + (typeof obj !== "function" || !reservedFunctionProperties.has(key)) && + // Don't add property from a higher prototype if it already exists in a lower one + addToSeen(seen, key)) { + const value = safeGetPropertyOfObject(chain, key); + // Don't repeat "toString" that matches signature from Object.prototype + if (!(key === "toString" && typeof value === "function" && value.length === 0)) { + entries.push({ key, value }); + } + } + } + chain = Object.getPrototypeOf(chain); + } + return entries.sort((e1, e2) => compareStringsCaseSensitive(e1.key, e2.key)); + } + + function getFunctionLength(fn: AnyFunction): number { + return tryCast(safeGetPropertyOfObject(fn, "length"), isNumber) || 0; + } + + function safeGetPropertyOfObject(obj: object, key: string): unknown { + const desc = Object.getOwnPropertyDescriptor(obj, key); + return desc && desc.value; + } + + function isNullOrUndefined(value: unknown): value is null | undefined { + return value == null; // tslint:disable-line + } + + function anyValue(name: string, comment?: string): ValueInfo { + return { kind: ValueKind.Const, name, typeName: "any", comment }; + } + + export function isJsPrivate(name: string): boolean { + return name.startsWith("_"); + } + + function tryRequire(fileNameToRequire: string): unknown { + try { + return require(fileNameToRequire); + } + catch { + return undefined; + } + } +} diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 335e47286b7..1d912faa116 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -779,14 +779,23 @@ namespace ts { */ /* @internal */ export function resolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string { - const { resolvedModule, failedLookupLocations } = - nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true); + const { resolvedModule, failedLookupLocations } = tryResolveJSModuleWorker(moduleName, initialDir, host); if (!resolvedModule) { throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations.join(", ")}`); } return resolvedModule.resolvedFileName; } + /* @internal */ + export function tryResolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string | undefined { + const { resolvedModule } = tryResolveJSModuleWorker(moduleName, initialDir, host); + return resolvedModule && resolvedModule.resolvedFileName; + } + + function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { + return nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true); + } + export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations { return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false); } diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 2d3cbcf54fe..4822f1dc06a 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -52,6 +52,7 @@ "resolutionCache.ts", "moduleSpecifiers.ts", "watch.ts", - "tsbuild.ts" + "tsbuild.ts", + "inspectValue.ts", ] } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index fb1ed9fcb1b..c06e95339f1 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2502,9 +2502,7 @@ Actual: ${stringify(fullActual)}`); const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings, ts.emptyOptions); assert.deepEqual | undefined>(commands, expectedCommands); - assert(changes.every(c => c.fileName === this.activeFile.fileName), "TODO: support testing codefixes that touch multiple files"); - this.applyChanges(changes); - this.verifyCurrentFileContent(newFileContent); + this.verifyNewContent({ newFileContent }, changes); } /** @@ -3389,6 +3387,19 @@ Actual: ${stringify(fullActual)}`); private getApplicableRefactorsWorker(positionOrRange: number | ts.TextRange, fileName: string, preferences = ts.emptyOptions): ReadonlyArray { return this.languageService.getApplicableRefactors(fileName, positionOrRange, preferences) || ts.emptyArray; } + + public generateTypes(examples: ReadonlyArray): void { + for (const { name = "example", value, output, outputBaseline } of examples) { + const actual = ts.generateTypesForModule(name, value, this.formatCodeSettings); + if (outputBaseline) { + if (actual === undefined) throw ts.Debug.fail(); + Harness.Baseline.runBaseline(ts.combinePaths("generateTypes", outputBaseline + ts.Extension.Dts), actual); + } + else { + assert.equal(actual, output, `generateTypes output for ${name} does not match`); + } + } + } } function updateTextRangeForTextChanges({ pos, end }: ts.TextRange, textChanges: ReadonlyArray): ts.TextRange { @@ -3442,7 +3453,7 @@ Actual: ${stringify(fullActual)}`); // Parse out the files and their metadata const testData = parseTestData(absoluteBasePath, content, absoluteFileName); const state = new TestState(absoluteBasePath, testType, testData); - const output = ts.transpileModule(content, { reportDiagnostics: true }); + const output = ts.transpileModule(content, { reportDiagnostics: true, compilerOptions: { target: ts.ScriptTarget.ES2015 } }); if (output.diagnostics!.length > 0) { throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics![0].messageText}`); } @@ -4512,6 +4523,18 @@ namespace FourSlashInterface { public noMoveToNewFile(): void { this.state.noMoveToNewFile(); } + + public generateTypes(...options: GenerateTypesOptions[]): void { + this.state.generateTypes(options); + } + } + + export interface GenerateTypesOptions { + readonly name?: string; + readonly value: unknown; + // Exactly one of these should be set: + readonly output?: string; + readonly outputBaseline?: string; } export class Edit { @@ -4901,7 +4924,7 @@ namespace FourSlashInterface { export interface VerifyCodeFixAllOptions { fixId: string; fixAllDescription: string; - newFileContent: string; + newFileContent: NewFileContent; commands: ReadonlyArray<{}>; } diff --git a/src/jsTyping/shared.ts b/src/jsTyping/shared.ts index 54b34193d06..78e9fe051b7 100644 --- a/src/jsTyping/shared.ts +++ b/src/jsTyping/shared.ts @@ -4,6 +4,7 @@ namespace ts.server { export const ActionSet: ActionSet = "action::set"; export const ActionInvalidate: ActionInvalidate = "action::invalidate"; export const ActionPackageInstalled: ActionPackageInstalled = "action::packageInstalled"; + export const ActionValueInspected: ActionValueInspected = "action::valueInspected"; export const EventTypesRegistry: EventTypesRegistry = "event::typesRegistry"; export const EventBeginInstallTypes: EventBeginInstallTypes = "event::beginInstallTypes"; export const EventEndInstallTypes: EventEndInstallTypes = "event::endInstallTypes"; diff --git a/src/jsTyping/types.ts b/src/jsTyping/types.ts index 4e00c2eb6f5..408d30a6511 100644 --- a/src/jsTyping/types.ts +++ b/src/jsTyping/types.ts @@ -2,6 +2,7 @@ declare namespace ts.server { export type ActionSet = "action::set"; export type ActionInvalidate = "action::invalidate"; export type ActionPackageInstalled = "action::packageInstalled"; + export type ActionValueInspected = "action::valueInspected"; export type EventTypesRegistry = "event::typesRegistry"; export type EventBeginInstallTypes = "event::beginInstallTypes"; export type EventEndInstallTypes = "event::endInstallTypes"; @@ -12,7 +13,7 @@ declare namespace ts.server { } export interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; } export interface TypingInstallerRequestWithProjectName { @@ -20,7 +21,7 @@ declare namespace ts.server { } /* @internal */ - export type TypingInstallerRequestUnion = DiscoverTypings | CloseProject | TypesRegistryRequest | InstallPackageRequest; + export type TypingInstallerRequestUnion = DiscoverTypings | CloseProject | TypesRegistryRequest | InstallPackageRequest | InspectValueRequest; export interface DiscoverTypings extends TypingInstallerRequestWithProjectName { readonly fileNames: string[]; @@ -47,6 +48,12 @@ declare namespace ts.server { readonly projectRootPath: Path; } + /* @internal */ + export interface InspectValueRequest { + readonly kind: "inspectValue"; + readonly options: InspectValueOptions; + } + /* @internal */ export interface TypesRegistryResponse extends TypingInstallerResponse { readonly kind: EventTypesRegistry; @@ -59,6 +66,12 @@ declare namespace ts.server { readonly message: string; } + /* @internal */ + export interface InspectValueResponse { + readonly kind: ActionValueInspected; + readonly result: ValueInfo; + } + export interface InitializationFailedResponse extends TypingInstallerResponse { readonly kind: EventInitializationFailed; readonly message: string; @@ -106,5 +119,5 @@ declare namespace ts.server { } /* @internal */ - export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InstallTypes | InitializationFailedResponse; + export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InspectValueResponse | InstallTypes | InitializationFailedResponse; } diff --git a/src/server/project.ts b/src/server/project.ts index 3cabc8793db..89b54a56c24 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -254,6 +254,11 @@ namespace ts.server { installPackage(options: InstallPackageOptions): Promise { return this.typingsCache.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) }); } + /* @internal */ + inspectValue(options: InspectValueOptions): Promise { + return this.typingsCache.inspectValue(options); + } + private get typingsCache(): TypingsCache { return this.projectService.typingsCache; } @@ -352,6 +357,10 @@ namespace ts.server { return this.projectService.host.readFile(fileName); } + writeFile(fileName: string, content: string): void { + return this.projectService.host.writeFile(fileName, content); + } + fileExists(file: string): boolean { // As an optimization, don't hit the disks for files we already know don't exist // (because we're watching for their creation). diff --git a/src/server/session.ts b/src/server/session.ts index 977a0bd186d..688bccb935c 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1829,8 +1829,8 @@ namespace ts.server { private applyCodeActionCommand(args: protocol.ApplyCodeActionCommandRequestArgs): {} { const commands = args.command as CodeActionCommand | CodeActionCommand[]; // They should be sending back the command we sent them. for (const command of toArray(commands)) { - const { project } = this.getFileAndProject(command); - project.getLanguageService().applyCodeActionCommand(command).then( + const { file, project } = this.getFileAndProject(command); + project.getLanguageService().applyCodeActionCommand(command, this.getFormatOptions(file)).then( _result => { /* TODO: GH#20447 report success message? */ }, _error => { /* TODO: GH#20447 report errors */ }); } diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index 12b2303cfd3..64a117bbe25 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -8,6 +8,8 @@ namespace ts.server { export interface ITypingsInstaller { isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptionsWithProject): Promise; + /* @internal */ + inspectValue(options: InspectValueOptions): Promise; enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray | undefined): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; @@ -18,6 +20,7 @@ namespace ts.server { isKnownTypesPackageName: returnFalse, // Should never be called because we never provide a types registry. installPackage: notImplemented, + inspectValue: notImplemented, enqueueInstallTypingsRequest: noop, attach: noop, onProjectClosed: noop, @@ -95,6 +98,10 @@ namespace ts.server { return this.installer.installPackage(options); } + inspectValue(options: InspectValueOptions): Promise { + return this.installer.inspectValue(options); + } + enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray | undefined, forceRefresh: boolean) { const typeAcquisition = project.getTypeAcquisition(); diff --git a/src/services/codefixes/fixCannotFindModule.ts b/src/services/codefixes/fixCannotFindModule.ts index 6822cae7911..1c7070c74bf 100644 --- a/src/services/codefixes/fixCannotFindModule.ts +++ b/src/services/codefixes/fixCannotFindModule.ts @@ -1,6 +1,9 @@ /* @internal */ namespace ts.codefix { - const fixId = "fixCannotFindModule"; + const fixName = "fixCannotFindModule"; + const fixIdInstallTypesPackage = "installTypesPackage"; + const fixIdGenerateTypes = "generateTypes"; + const errorCodeCannotFindModule = Diagnostics.Cannot_find_module_0.code; const errorCodes = [ errorCodeCannotFindModule, @@ -10,26 +13,141 @@ namespace ts.codefix { errorCodes, getCodeActions: context => { const { host, sourceFile, span: { start } } = context; - const packageName = getTypesPackageNameToInstall(host, sourceFile, start, context.errorCode); - return packageName === undefined ? [] - : [createCodeFixAction(fixId, /*changes*/ [], [Diagnostics.Install_0, packageName], fixId, Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))]; + const packageName = tryGetImportedPackageName(sourceFile, start); + if (packageName === undefined) return undefined; + const typesPackageName = getTypesPackageNameToInstall(packageName, host, context.errorCode); + return typesPackageName === undefined + ? singleElementArray(tryGetGenerateTypesAction(context, packageName)) + : [createCodeFixAction(fixName, /*changes*/ [], [Diagnostics.Install_0, typesPackageName], fixIdInstallTypesPackage, Diagnostics.Install_all_missing_types_packages, getInstallCommand(sourceFile.fileName, typesPackageName))]; + }, + fixIds: [fixIdInstallTypesPackage, fixIdGenerateTypes], + getAllCodeActions: context => { + let savedTypesDir: string | null | undefined = null; // tslint:disable-line no-null-keyword + return codeFixAll(context, errorCodes, (changes, diag, commands) => { + const packageName = tryGetImportedPackageName(diag.file, diag.start); + if (packageName === undefined) return undefined; + switch (context.fixId) { + case fixIdInstallTypesPackage: { + const pkg = getTypesPackageNameToInstall(packageName, context.host, diag.code); + if (pkg) { + commands.push(getInstallCommand(diag.file.fileName, pkg)); + } + break; + } + case fixIdGenerateTypes: { + const typesDir = savedTypesDir !== null ? savedTypesDir : savedTypesDir = getOrCreateTypesDirectory(changes, context); + const command = typesDir === undefined ? undefined : tryGenerateTypes(typesDir, packageName, context); + if (command) commands.push(command); + break; + } + default: + Debug.fail(`Bad fixId: ${context.fixId}`); + } + }); }, - fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (_, diag, commands) => { - const pkg = getTypesPackageNameToInstall(context.host, diag.file, diag.start, diag.code); - if (pkg) { - commands.push(getCommand(diag.file.fileName, pkg)); - } - }), }); - function getCommand(fileName: string, packageName: string): InstallPackageAction { + function tryGetGenerateTypesAction(context: CodeFixContextBase, packageName: string): CodeFixAction | undefined { + let command: GenerateTypesAction | undefined; + const changes = textChanges.ChangeTracker.with(context, t => { + const typesDir = getOrCreateTypesDirectory(t, context); + command = typesDir === undefined ? undefined : tryGenerateTypes(typesDir, packageName, context); + }); + return command && createCodeFixAction(fixName, changes, [Diagnostics.Generate_types_for_0, packageName], fixIdGenerateTypes, Diagnostics.Generate_types_for_all_packages_without_types, command); + } + + function tryGenerateTypes(typesDir: string, packageName: string, context: CodeFixContextBase): GenerateTypesAction | undefined { + const file = context.sourceFile.fileName; + const fileToGenerateTypesFor = tryResolveJSModule(packageName, getDirectoryPath(file), context.host as ModuleResolutionHost); // TODO: GH#18217 + if (fileToGenerateTypesFor === undefined) return undefined; + + const outputFileName = resolvePath(getDirectoryPath(context.program.getCompilerOptions().configFile!.fileName), typesDir, packageName + ".d.ts"); + if (context.host.fileExists!(outputFileName)) return undefined; + return { type: "generate types", file, fileToGenerateTypesFor, outputFileName }; + } + + // If no types directory exists yet, adds it to tsconfig.json + function getOrCreateTypesDirectory(changes: textChanges.ChangeTracker, context: CodeFixContextBase): string | undefined { + const { configFile } = context.program.getCompilerOptions(); + if (!configFile) return undefined; + + const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile); + if (!tsconfigObjectLiteral) return undefined; + + const compilerOptionsProperty = findProperty(tsconfigObjectLiteral, "compilerOptions"); + if (!compilerOptionsProperty) { + const newCompilerOptions = createObjectLiteral([makeDefaultBaseUrl(), makeDefaultPaths()]); + changes.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment("compilerOptions", newCompilerOptions)); + return defaultTypesDirectoryName; + } + + const compilerOptions = compilerOptionsProperty.initializer; + if (!isObjectLiteralExpression(compilerOptions)) return defaultTypesDirectoryName; + + const baseUrl = getOrAddBaseUrl(changes, configFile, compilerOptions); + const typesDirectoryFromPathMapping = getOrAddPathMapping(changes, configFile, compilerOptions); + return combinePaths(baseUrl, typesDirectoryFromPathMapping); + } + + const defaultBaseUrl = "."; + function makeDefaultBaseUrl(): PropertyAssignment { + return createJsonPropertyAssignment("baseUrl", createStringLiteral(defaultBaseUrl)); + } + function getOrAddBaseUrl(changes: textChanges.ChangeTracker, tsconfig: TsConfigSourceFile, compilerOptions: ObjectLiteralExpression): string { + const baseUrlProp = findProperty(compilerOptions, "baseUrl"); + if (baseUrlProp) { + return isStringLiteral(baseUrlProp.initializer) ? baseUrlProp.initializer.text : defaultBaseUrl; + } + else { + changes.insertNodeAtObjectStart(tsconfig, compilerOptions, makeDefaultBaseUrl()); + return defaultBaseUrl; + } + } + + const defaultTypesDirectoryName = "types"; + function makeDefaultPathMapping(): PropertyAssignment { + return createJsonPropertyAssignment("*", createArrayLiteral([createStringLiteral(`${defaultTypesDirectoryName}/*`)])); + } + function makeDefaultPaths(): PropertyAssignment { + return createJsonPropertyAssignment("paths", createObjectLiteral([makeDefaultPathMapping()])); + } + function getOrAddPathMapping(changes: textChanges.ChangeTracker, tsconfig: TsConfigSourceFile, compilerOptions: ObjectLiteralExpression) { + const paths = findProperty(compilerOptions, "paths"); + if (!paths || !isObjectLiteralExpression(paths.initializer)) { + changes.insertNodeAtObjectStart(tsconfig, compilerOptions, makeDefaultPaths()); + return defaultTypesDirectoryName; + } + + // Look for an existing path mapping. Should look like `"*": "foo/*"`. + const existing = firstDefined(paths.initializer.properties, prop => + isPropertyAssignment(prop) && isStringLiteral(prop.name) && prop.name.text === "*" && isArrayLiteralExpression(prop.initializer) + ? firstDefined(prop.initializer.elements, value => isStringLiteral(value) ? tryRemoveSuffix(value.text, "/*") : undefined) + : undefined); + if (existing) return existing; + + changes.insertNodeAtObjectStart(tsconfig, paths.initializer, makeDefaultPathMapping()); + return defaultTypesDirectoryName; + } + + function createJsonPropertyAssignment(name: string, initializer: Expression) { + return createPropertyAssignment(createStringLiteral(name), initializer); + } + + function findProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined { + return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name); + } + + function getInstallCommand(fileName: string, packageName: string): InstallPackageAction { return { type: "install package", file: fileName, packageName }; } - function getTypesPackageNameToInstall(host: LanguageServiceHost, sourceFile: SourceFile, pos: number, diagCode: number): string | undefined { + function tryGetImportedPackageName(sourceFile: SourceFile, pos: number): string | undefined { const moduleName = cast(getTokenAtPosition(sourceFile, pos), isStringLiteral).text; const { packageName } = parsePackageName(moduleName); + return isExternalModuleNameRelative(packageName) ? undefined : packageName; + } + + function getTypesPackageNameToInstall(packageName: string, host: LanguageServiceHost, diagCode: number): string | undefined { return diagCode === errorCodeCannotFindModule ? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined) : (host.isKnownTypesPackageName!(packageName) ? getTypesPackageName(packageName) : undefined); // TODO: GH#18217 diff --git a/src/services/codefixes/generateTypes.ts b/src/services/codefixes/generateTypes.ts new file mode 100644 index 00000000000..6af72da562d --- /dev/null +++ b/src/services/codefixes/generateTypes.ts @@ -0,0 +1,227 @@ +/* @internal */ +namespace ts { + export function generateTypesForModule(name: string, moduleValue: unknown, formatSettings: FormatCodeSettings): string { + return valueInfoToDeclarationFileText(inspectValue(name, moduleValue), formatSettings); + } + + export function valueInfoToDeclarationFileText(valueInfo: ValueInfo, formatSettings: FormatCodeSettings): string { + return textChanges.getNewFileText(toStatements(valueInfo, OutputKind.ExportEquals), ScriptKind.TS, "\n", formatting.getFormatContext(formatSettings)); + } + + const enum OutputKind { ExportEquals, NamedExport, NamespaceMember } + function toNamespaceMemberStatements(info: ValueInfo): ReadonlyArray { + return toStatements(info, OutputKind.NamespaceMember); + } + function toStatements(info: ValueInfo, kind: OutputKind): ReadonlyArray { + const isDefault = info.name === InternalSymbolName.Default; + const name = isDefault ? "_default" : info.name; + if (!isValidIdentifier(name) || isDefault && kind !== OutputKind.NamedExport) return emptyArray; + + const modifiers = isDefault && info.kind === ValueKind.FunctionOrClass ? [createModifier(SyntaxKind.ExportKeyword), createModifier(SyntaxKind.DefaultKeyword)] + : kind === OutputKind.ExportEquals ? [createModifier(SyntaxKind.DeclareKeyword)] + : kind === OutputKind.NamedExport ? [createModifier(SyntaxKind.ExportKeyword)] + : undefined; + const exportEquals = () => kind === OutputKind.ExportEquals ? [exportEqualsOrDefault(info.name, /*isExportEquals*/ true)] : emptyArray; + const exportDefault = () => isDefault ? [exportEqualsOrDefault("_default", /*isExportEquals*/ false)] : emptyArray; + + switch (info.kind) { + case ValueKind.FunctionOrClass: + return [...exportEquals(), ...functionOrClassToStatements(modifiers, name, info)]; + case ValueKind.Object: + const { members } = info; + if (kind === OutputKind.ExportEquals) { + return flatMap(members, v => toStatements(v, OutputKind.NamedExport)); + } + if (members.some(m => m.kind === ValueKind.FunctionOrClass)) { + // If some member is a function, use a namespace so it gets a FunctionDeclaration or ClassDeclaration. + return [...exportDefault(), createNamespace(modifiers, name, flatMap(members, toNamespaceMemberStatements))]; + } + // falls through + case ValueKind.Const: + case ValueKind.Array: { + const comment = info.kind === ValueKind.Const ? info.comment : undefined; + const constVar = createVariableStatement(modifiers, createVariableDeclarationList([createVariableDeclaration(name, toType(info))], NodeFlags.Const)); + return [...exportEquals(), ...exportDefault(), addComment(constVar, comment)]; + } + default: + return Debug.assertNever(info); + } + } + function exportEqualsOrDefault(name: string, isExportEquals: boolean): ExportAssignment { + return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, isExportEquals, createIdentifier(name)); + } + + function functionOrClassToStatements(modifiers: Modifiers, name: string, { source, prototypeMembers, namespaceMembers }: ValueInfoFunctionOrClass): ReadonlyArray { + const fnAst = parseClassOrFunctionBody(source); + const { parameters, returnType } = fnAst === undefined ? { parameters: emptyArray, returnType: anyType() } : getParametersAndReturnType(fnAst); + const instanceProperties = typeof fnAst === "object" ? getConstructorFunctionInstanceProperties(fnAst) : emptyArray; + + const classStaticMembers: ClassElement[] | undefined = + instanceProperties.length !== 0 || prototypeMembers.length !== 0 || fnAst === undefined || typeof fnAst !== "number" && fnAst.kind === SyntaxKind.Constructor ? [] : undefined; + + const namespaceStatements = flatMap(namespaceMembers, info => { + if (!isValidIdentifier(info.name)) return undefined; + if (classStaticMembers) { + switch (info.kind) { + case ValueKind.Object: + if (info.members.some(m => m.kind === ValueKind.FunctionOrClass)) { + break; + } + // falls through + case ValueKind.Array: + case ValueKind.Const: + classStaticMembers.push( + addComment( + createProperty(/*decorators*/ undefined, [createModifier(SyntaxKind.StaticKeyword)], info.name, /*questionOrExclamationToken*/ undefined, toType(info), /*initializer*/ undefined), + info.kind === ValueKind.Const ? info.comment : undefined)); + return undefined; + case ValueKind.FunctionOrClass: + if (!info.namespaceMembers.length) { // Else, can't merge a static method with a namespace. Must make it a function on the namespace. + const sig = tryGetMethod(info, [createModifier(SyntaxKind.StaticKeyword)]); + if (sig) { + classStaticMembers.push(sig); + return undefined; + } + } + } + } + return toStatements(info, OutputKind.NamespaceMember); + }); + + const decl = classStaticMembers + ? createClassDeclaration( + /*decorators*/ undefined, + modifiers, + name, + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + [ + ...classStaticMembers, + ...(parameters.length ? [createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, /*body*/ undefined)] : emptyArray), + ...instanceProperties, + // ignore non-functions on the prototype + ...mapDefined(prototypeMembers, info => info.kind === ValueKind.FunctionOrClass ? tryGetMethod(info) : undefined), + ]) + : createFunctionDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, name, /*typeParameters*/ undefined, parameters, returnType, /*body*/ undefined); + return [decl, ...(namespaceStatements.length === 0 ? emptyArray : [createNamespace(modifiers && modifiers.map(m => getSynthesizedDeepClone(m)), name, namespaceStatements)])]; + } + + function tryGetMethod({ name, source }: ValueInfoFunctionOrClass, modifiers?: Modifiers): MethodDeclaration | undefined { + if (!isValidIdentifier(name)) return undefined; + const fnAst = parseClassOrFunctionBody(source); + if (fnAst === undefined || (typeof fnAst !== "number" && fnAst.kind === SyntaxKind.Constructor)) return undefined; + const sig = getParametersAndReturnType(fnAst); + return sig && createMethod( + /*decorators*/ undefined, + modifiers, + /*asteriskToken*/ undefined, + name, + /*questionToken*/ undefined, + /*typeParameters*/ undefined, + sig.parameters, + sig.returnType, + /*body*/ undefined); + } + + function toType(info: ValueInfo): TypeNode { + switch (info.kind) { + case ValueKind.Const: + return createTypeReferenceNode(info.typeName, /*typeArguments*/ undefined); + case ValueKind.Array: + return createArrayTypeNode(toType(info.inner)); + case ValueKind.FunctionOrClass: + return createTypeReferenceNode("Function", /*typeArguments*/ undefined); // Normally we create a FunctionDeclaration, but this can happen for a function in an array. + case ValueKind.Object: + return createTypeLiteralNode(info.members.map(m => createPropertySignature(/*modifiers*/ undefined, m.name, /*questionToken*/ undefined, toType(m), /*initializer*/ undefined))); + default: + return Debug.assertNever(info); + } + } + + // Parses assignments to "this.x" in the constructor into class property declarations + function getConstructorFunctionInstanceProperties(fnAst: FunctionOrConstructorNode): ReadonlyArray { + const members: PropertyDeclaration[] = []; + forEachOwnNodeOfFunction(fnAst, node => { + if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true) && + isPropertyAccessExpression(node.left) && node.left.expression.kind === SyntaxKind.ThisKeyword) { + const name = node.left.name.text; + if (!isJsPrivate(name)) members.push(createProperty(/*decorators*/ undefined, /*modifiers*/ undefined, name, /*questionOrExclamationToken*/ undefined, anyType(), /*initializer*/ undefined)); + } + }); + return members; + } + + interface ParametersAndReturnType { readonly parameters: ReadonlyArray; readonly returnType: TypeNode; } + function getParametersAndReturnType(fnAst: FunctionOrConstructor): ParametersAndReturnType { + if (typeof fnAst === "number") { + return { parameters: fill(fnAst, i => makeParameter(`p${i}`, anyType())), returnType: anyType() }; + } + let usedArguments = false, hasReturn = false; + forEachOwnNodeOfFunction(fnAst, node => { + usedArguments = usedArguments || isIdentifier(node) && node.text === "arguments"; + hasReturn = hasReturn || isReturnStatement(node) && !!node.expression && node.expression.kind !== SyntaxKind.VoidExpression; + }); + const parameters = [ + ...fnAst.parameters.map(p => makeParameter(`${p.name.getText()}`, inferParameterType(fnAst, p))), + ...(usedArguments ? [makeRestParameter()] : emptyArray), + ]; + return { parameters, returnType: hasReturn ? anyType() : createKeywordTypeNode(SyntaxKind.VoidKeyword) }; + } + function makeParameter(name: string, type: TypeNode): ParameterDeclaration { + return createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name, /*questionToken*/ undefined, type); + } + function makeRestParameter(): ParameterDeclaration { + return createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, createToken(SyntaxKind.DotDotDotToken), "args", /*questionToken*/ undefined, createArrayTypeNode(anyType())); + } + + type FunctionOrConstructorNode = FunctionExpression | ArrowFunction | ConstructorDeclaration | MethodDeclaration; + type FunctionOrConstructor = FunctionOrConstructorNode | number; // number is for native function + /** Returns 'undefined' for class with no declared constructor */ + function parseClassOrFunctionBody(source: string | number): FunctionOrConstructor | undefined { + if (typeof source === "number") return source; + const classOrFunction = tryCast(parseExpression(source), (node): node is FunctionExpression | ArrowFunction | ClassExpression => isFunctionExpression(node) || isArrowFunction(node) || isClassExpression(node)); + return classOrFunction + ? isClassExpression(classOrFunction) ? find(classOrFunction.members, isConstructorDeclaration) : classOrFunction + // If that didn't parse, it's a method `m() {}`. Parse again inside of an object literal. + : cast(first(cast(parseExpression(`{ ${source} }`), isObjectLiteralExpression).properties), isMethodDeclaration); + } + + function parseExpression(expr: string): Expression { + const text = `const _ = ${expr}`; + const srcFile = createSourceFile("test.ts", text, ScriptTarget.Latest, /*setParentNodes*/ true); + return first(cast(first(srcFile.statements), isVariableStatement).declarationList.declarations).initializer!; + } + + function inferParameterType(_fn: FunctionOrConstructor, _param: ParameterDeclaration): TypeNode { + // TODO: Inspect function body for clues (see inferFromUsage.ts) + return anyType(); + } + + // Descends through all nodes in a function, but not in nested functions. + function forEachOwnNodeOfFunction(fnAst: FunctionOrConstructorNode, cb: (node: Node) => void) { + fnAst.body!.forEachChild(function recur(node) { + cb(node); + if (!isFunctionLike(node)) node.forEachChild(recur); + }); + } + + function isValidIdentifier(name: string): boolean { + const keyword = stringToToken(name); + return !(keyword && isNonContextualKeyword(keyword)) && isIdentifierText(name, ScriptTarget.ESNext); + } + + type Modifiers = ReadonlyArray | undefined; + + function addComment(node: T, comment: string | undefined): T { + if (comment !== undefined) addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, comment); + return node; + } + + function anyType(): KeywordTypeNode { + return createKeywordTypeNode(SyntaxKind.AnyKeyword); + } + + function createNamespace(modifiers: Modifiers, name: string, statements: ReadonlyArray): NamespaceDeclaration { + return createModuleDeclaration(/*decorators*/ undefined, modifiers, createIdentifier(name), createModuleBlock(statements), NodeFlags.Namespace) as NamespaceDeclaration; + } +} diff --git a/src/services/services.ts b/src/services/services.ts index 57c45359179..5a035a92bcd 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1808,25 +1808,36 @@ namespace ts { return ts.getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions), preferences, sourceMapper); } - function applyCodeActionCommand(action: CodeActionCommand): Promise; - function applyCodeActionCommand(action: CodeActionCommand[]): Promise; - function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise; + function applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; + function applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; function applyCodeActionCommand(fileName: Path, action: CodeActionCommand): Promise; function applyCodeActionCommand(fileName: Path, action: CodeActionCommand[]): Promise; - function applyCodeActionCommand(fileName: Path | CodeActionCommand | CodeActionCommand[], actionOrUndefined?: CodeActionCommand | CodeActionCommand[]): Promise { - const action = typeof fileName === "string" ? actionOrUndefined! : fileName as CodeActionCommand[]; - return isArray(action) ? Promise.all(action.map(applySingleCodeActionCommand)) : applySingleCodeActionCommand(action); + function applyCodeActionCommand(fileName: Path | CodeActionCommand | CodeActionCommand[], actionOrFormatSettingsOrUndefined?: CodeActionCommand | CodeActionCommand[] | FormatCodeSettings): Promise { + const action = typeof fileName === "string" ? actionOrFormatSettingsOrUndefined as CodeActionCommand | CodeActionCommand[] : fileName as CodeActionCommand[]; + const formatSettings = typeof fileName !== "string" ? actionOrFormatSettingsOrUndefined as FormatCodeSettings : undefined; + return isArray(action) ? Promise.all(action.map(a => applySingleCodeActionCommand(a, formatSettings))) : applySingleCodeActionCommand(action, formatSettings); } - function applySingleCodeActionCommand(action: CodeActionCommand): Promise { + function applySingleCodeActionCommand(action: CodeActionCommand, formatSettings: FormatCodeSettings | undefined): Promise { + const getPath = (path: string): Path => toPath(path, currentDirectory, getCanonicalFileName); switch (action.type) { case "install package": return host.installPackage - ? host.installPackage({ fileName: toPath(action.file, currentDirectory, getCanonicalFileName), packageName: action.packageName }) + ? host.installPackage({ fileName: getPath(action.file), packageName: action.packageName }) : Promise.reject("Host does not implement `installPackage`"); + case "generate types": { + const { fileToGenerateTypesFor, outputFileName } = action; + if (!host.inspectValue) return Promise.reject("Host does not implement `installPackage`"); + const valueInfoPromise = host.inspectValue({ fileNameToRequire: fileToGenerateTypesFor }); + return valueInfoPromise.then(valueInfo => { + const fullOut = getPath(outputFileName); + host.writeFile!(fullOut, valueInfoToDeclarationFileText(valueInfo, formatSettings || testFormatSettings)); // TODO: GH#18217 + return { successMessage: `Wrote types to '${fullOut}'` }; + }); + } default: - return Debug.fail(); - // TODO: Debug.assertNever(action); will only work if there is more than one type. + return Debug.assertNever(action); } } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 99b94c2cc86..756d2799a28 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -211,8 +211,8 @@ namespace ts.textChanges { export class ChangeTracker { private readonly changes: Change[] = []; - private readonly newFiles: { readonly oldFile: SourceFile, readonly fileName: string, readonly statements: ReadonlyArray }[] = []; - private readonly classesWithNodesInsertedAtStart = createMap(); // Set implemented as Map + private readonly newFiles: { readonly oldFile: SourceFile | undefined, readonly fileName: string, readonly statements: ReadonlyArray }[] = []; + private readonly classesWithNodesInsertedAtStart = createMap<{ readonly node: ClassDeclaration | InterfaceDeclaration | ObjectLiteralExpression, readonly sourceFile: SourceFile }>(); // Set implemented as Map private readonly deletedNodes: { readonly sourceFile: SourceFile, readonly node: Node | NodeArray }[] = []; public static fromContext(context: TextChangesContext): ChangeTracker { @@ -410,25 +410,33 @@ namespace ts.textChanges { } public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration, newElement: ClassElement): void { + this.insertNodeAtStartWorker(sourceFile, cls, newElement); + } + public insertNodeAtObjectStart(sourceFile: SourceFile, obj: ObjectLiteralExpression, newElement: ObjectLiteralElementLike): void { + this.insertNodeAtStartWorker(sourceFile, obj, newElement); + } + + private insertNodeAtStartWorker(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, newElement: ClassElement | ObjectLiteralElementLike): void { const clsStart = cls.getStart(sourceFile); const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options) + this.formatContext.options.indentSize!; - this.insertNodeAt(sourceFile, cls.members.pos, newElement, { indentation, ...this.getInsertNodeAtClassStartPrefixSuffix(sourceFile, cls) }); + this.insertNodeAt(sourceFile, getMembersOrProperties(cls).pos, newElement, { indentation, ...this.getInsertNodeAtStartPrefixSuffix(sourceFile, cls) }); } - private getInsertNodeAtClassStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration): { prefix: string, suffix: string } { - if (cls.members.length === 0) { - if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), cls)) { + private getInsertNodeAtStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): { prefix: string, suffix: string } { + const comma = isObjectLiteralExpression(cls) ? "," : ""; + if (getMembersOrProperties(cls).length === 0) { + if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), { node: cls, sourceFile })) { // For `class C {\n}`, don't add the trailing "\n" - const shouldSuffix = (positionsAreOnSameLine as any)(...getClassBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any' - return { prefix: this.newLineCharacter, suffix: shouldSuffix ? this.newLineCharacter : "" }; + const shouldSuffix = (positionsAreOnSameLine as any)(...getClassOrObjectBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any' + return { prefix: this.newLineCharacter, suffix: comma + (shouldSuffix ? this.newLineCharacter : "") }; } else { - return { prefix: "", suffix: this.newLineCharacter }; + return { prefix: "", suffix: comma + this.newLineCharacter }; } } else { - return { prefix: this.newLineCharacter, suffix: "" }; + return { prefix: this.newLineCharacter, suffix: comma }; } } @@ -647,9 +655,8 @@ namespace ts.textChanges { } private finishClassesWithNodesInsertedAtStart(): void { - this.classesWithNodesInsertedAtStart.forEach(cls => { - const sourceFile = cls.getSourceFile(); - const [openBraceEnd, closeBraceEnd] = getClassBraceEnds(cls, sourceFile); + this.classesWithNodesInsertedAtStart.forEach(({ node, sourceFile }) => { + const [openBraceEnd, closeBraceEnd] = getClassOrObjectBraceEnds(node, sourceFile); // For `class C { }` remove the whitespace inside the braces. if (positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) { this.deleteRange(sourceFile, createRange(openBraceEnd, closeBraceEnd - 1)); @@ -698,7 +705,7 @@ namespace ts.textChanges { return changes; } - public createNewFile(oldFile: SourceFile, fileName: string, statements: ReadonlyArray) { + public createNewFile(oldFile: SourceFile | undefined, fileName: string, statements: ReadonlyArray) { this.newFiles.push({ oldFile, fileName, statements }); } } @@ -708,12 +715,19 @@ namespace ts.textChanges { return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } - function getClassBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration, sourceFile: SourceFile): [number, number] { + function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number, number] { return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile)!.end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)!.end]; } + function getMembersOrProperties(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): NodeArray { + return isObjectLiteralExpression(cls) ? cls.properties : cls.members; + } export type ValidateNonFormattedText = (node: Node, text: string) => void; + export function getNewFileText(statements: ReadonlyArray, scriptKind: ScriptKind, newLineCharacter: string, formatContext: formatting.FormatContext): string { + return changesToText.newFileChangesWorker(/*oldFile*/ undefined, scriptKind, statements, newLineCharacter, formatContext); + } + namespace changesToText { export function getTextChangesFromChanges(changes: ReadonlyArray, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): FileTextChanges[] { return group(changes, c => c.sourceFile.path).map(changesInFile => { @@ -732,13 +746,17 @@ namespace ts.textChanges { }); } - export function newFileChanges(oldFile: SourceFile, fileName: string, statements: ReadonlyArray, newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges { + export function newFileChanges(oldFile: SourceFile | undefined, fileName: string, statements: ReadonlyArray, newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges { + const text = newFileChangesWorker(oldFile, getScriptKindFromFileName(fileName), statements, newLineCharacter, formatContext); + return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true }; + } + + export function newFileChangesWorker(oldFile: SourceFile | undefined, scriptKind: ScriptKind, statements: ReadonlyArray, newLineCharacter: string, formatContext: formatting.FormatContext): string { // TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this const nonFormattedText = statements.map(s => getNonformattedText(s, oldFile, newLineCharacter).text).join(newLineCharacter); - const sourceFile = createSourceFile(fileName, nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true); + const sourceFile = createSourceFile("any file name", nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true, scriptKind); const changes = formatting.formatDocument(sourceFile, formatContext); - const text = applyChanges(nonFormattedText, changes); - return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true }; + return applyChanges(nonFormattedText, changes); } function computeNewText(change: Change, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index fee6da0f8a3..6f718b43730 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -69,6 +69,7 @@ "codefixes/inferFromUsage.ts", "codefixes/fixInvalidImportSyntax.ts", "codefixes/fixStrictClassInitialization.ts", + "codefixes/generateTypes.ts", "codefixes/requireInTs.ts", "codefixes/useDefaultImport.ts", "codefixes/fixAddModuleReferTypeMissingTypeof.ts", @@ -82,6 +83,6 @@ "services.ts", "breakpoints.ts", "transform.ts", - "shims.ts" + "shims.ts", ] } diff --git a/src/services/types.ts b/src/services/types.ts index 08a09d7f912..dbf79cea783 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -231,6 +231,8 @@ namespace ts { isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; + /* @internal */ inspectValue?(options: InspectValueOptions): Promise; + writeFile?(fileName: string, content: string): void; } /* @internal */ @@ -331,9 +333,9 @@ namespace ts { getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; - applyCodeActionCommand(action: CodeActionCommand): Promise; - applyCodeActionCommand(action: CodeActionCommand[]): Promise; - applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise; + applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; + applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; /** @deprecated `fileName` will be ignored */ @@ -526,12 +528,22 @@ namespace ts { // Publicly, this type is just `{}`. Internally it is a union of all the actions we use. // See `commands?: {}[]` in protocol.ts - export type CodeActionCommand = InstallPackageAction; + export type CodeActionCommand = InstallPackageAction | GenerateTypesAction; export interface InstallPackageAction { - /* @internal */ file: string; - /* @internal */ type: "install package"; - /* @internal */ packageName: string; + /* @internal */ readonly type: "install package"; + /* @internal */ readonly file: string; + /* @internal */ readonly packageName: string; + } + + export interface GenerateTypesAction extends GenerateTypesOptions { + /* @internal */ readonly type: "generate types"; + } + + export interface GenerateTypesOptions { + readonly file: string; // File that was importing fileToGenerateTypesFor; used for formatting options. + readonly fileToGenerateTypesFor: string; + readonly outputFileName: string; } /** @@ -717,6 +729,31 @@ namespace ts { indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean; } + /* @internal */ + export const testFormatSettings: FormatCodeSettings = { + baseIndentSize: 0, + indentSize: 4, + tabSize: 4, + newLineCharacter: "\n", + convertTabsToSpaces: true, + indentStyle: IndentStyle.Smart, + insertSpaceAfterCommaDelimiter: true, + insertSpaceAfterSemicolonInForStatements: true, + insertSpaceBeforeAndAfterBinaryOperators: true, + insertSpaceAfterConstructor: false, + insertSpaceAfterKeywordsInControlFlowStatements: true, + insertSpaceAfterFunctionKeywordForAnonymousFunctions: false, + insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, + insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, + insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, + insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, + insertSpaceAfterTypeAssertion: false, + placeOpenBraceOnNewLineForFunctions: false, + placeOpenBraceOnNewLineForControlBlocks: false, + insertSpaceBeforeTypeAnnotation: false + }; + export interface DefinitionInfo extends DocumentSpan { kind: ScriptElementKind; name: string; diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index 88ea3d04aae..c1a08b3319c 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -292,7 +292,7 @@ interface Array {}` cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, preferences: emptyOptions, host: notImplementedHost, - formatContext: formatting.getFormatContext(testFormatOptions) + formatContext: formatting.getFormatContext(testFormatSettings) }; const diagnostics = languageService.getSuggestionDiagnostics(f.path); diff --git a/src/testRunner/unittests/extractTestHelpers.ts b/src/testRunner/unittests/extractTestHelpers.ts index 6e46c1304ab..6a74a637e92 100644 --- a/src/testRunner/unittests/extractTestHelpers.ts +++ b/src/testRunner/unittests/extractTestHelpers.ts @@ -64,27 +64,6 @@ namespace ts { } export const newLineCharacter = "\n"; - export const testFormatOptions: FormatCodeSettings = { - indentSize: 4, - tabSize: 4, - newLineCharacter, - convertTabsToSpaces: true, - indentStyle: IndentStyle.Smart, - insertSpaceAfterConstructor: false, - insertSpaceAfterCommaDelimiter: true, - insertSpaceAfterSemicolonInForStatements: true, - insertSpaceBeforeAndAfterBinaryOperators: true, - insertSpaceAfterKeywordsInControlFlowStatements: true, - insertSpaceAfterFunctionKeywordForAnonymousFunctions: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, - insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, - insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, - insertSpaceBeforeFunctionParenthesis: false, - placeOpenBraceOnNewLineForFunctions: false, - placeOpenBraceOnNewLineForControlBlocks: false, - }; export const notImplementedHost: LanguageServiceHost = { getCompilationSettings: notImplemented, @@ -123,7 +102,7 @@ namespace ts { startPosition: selectionRange.pos, endPosition: selectionRange.end, host: notImplementedHost, - formatContext: formatting.getFormatContext(testFormatOptions), + formatContext: formatting.getFormatContext(testFormatSettings), preferences: emptyOptions, }; const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange)); @@ -185,7 +164,7 @@ namespace ts { startPosition: selectionRange.pos, endPosition: selectionRange.end, host: notImplementedHost, - formatContext: formatting.getFormatContext(testFormatOptions), + formatContext: formatting.getFormatContext(testFormatSettings), preferences: emptyOptions, }; const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange)); diff --git a/src/testRunner/unittests/organizeImports.ts b/src/testRunner/unittests/organizeImports.ts index b4f54afa21b..355292c6d89 100644 --- a/src/testRunner/unittests/organizeImports.ts +++ b/src/testRunner/unittests/organizeImports.ts @@ -270,7 +270,7 @@ export const Other = 1; content: "function F() { }", }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatOptions, emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); assert.isEmpty(changes); }); @@ -741,7 +741,7 @@ export * from "lib"; function runBaseline(baselinePath: string, testFile: TestFSWithWatch.File, ...otherFiles: TestFSWithWatch.File[]) { const { path: testPath, content: testContent } = testFile; const languageService = makeLanguageService(testFile, ...otherFiles); - const changes = languageService.organizeImports({ type: "file", fileName: testPath }, testFormatOptions, emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testPath }, testFormatSettings, emptyOptions); assert.equal(changes.length, 1); assert.equal(changes[0].fileName, testPath); diff --git a/src/testRunner/unittests/textChanges.ts b/src/testRunner/unittests/textChanges.ts index 699f668b552..164073207b3 100644 --- a/src/testRunner/unittests/textChanges.ts +++ b/src/testRunner/unittests/textChanges.ts @@ -20,7 +20,7 @@ namespace ts { const newLineCharacter = getNewLineCharacter(printerOptions); function getRuleProvider(placeOpenBraceOnNewLineForFunctions: boolean): formatting.FormatContext { - return formatting.getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...testFormatOptions, placeOpenBraceOnNewLineForFunctions: true } : testFormatOptions); + return formatting.getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...testFormatSettings, placeOpenBraceOnNewLineForFunctions: true } : testFormatSettings); } // validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed. diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index ba3df56b7f2..639cd657e0d 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -85,6 +85,7 @@ namespace ts.projectSystem { isKnownTypesPackageName = notImplemented; installPackage = notImplemented; + inspectValue = notImplemented; executePendingCommands() { const actionsToRun = this.postExecActions; @@ -9092,7 +9093,7 @@ export const x = 10;` Debug.assert(!!project.resolveModuleNames); - const edits = project.getLanguageService().getEditsForFileRename("/old.ts", "/new.ts", testFormatOptions, emptyOptions); + const edits = project.getLanguageService().getEditsForFileRename("/old.ts", "/new.ts", testFormatSettings, emptyOptions); assert.deepEqual>(edits, [{ fileName: "/user.ts", textChanges: [{ diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 951b158c152..8084d42e1c5 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -231,7 +231,8 @@ namespace ts.server { // buffer, but we have yet to find a way to retrieve that value. private static readonly maxActiveRequestCount = 10; private static readonly requestDelayMillis = 100; - private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void } | undefined; + private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: unknown): void } | undefined; + private inspectValuePromise: { resolve(value: ValueInfo): void } | undefined; constructor( private readonly telemetryEnabled: boolean, @@ -261,14 +262,19 @@ namespace ts.server { } installPackage(options: InstallPackageOptionsWithProject): Promise { - const rq: InstallPackageRequest = { kind: "installPackage", ...options }; - this.send(rq); + this.send({ kind: "installPackage", ...options }); Debug.assert(this.packageInstalledPromise === undefined); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { this.packageInstalledPromise = { resolve, reject }; }); } + inspectValue(options: InspectValueOptions): Promise { + this.send({ kind: "inspectValue", options }); + Debug.assert(this.inspectValuePromise === undefined); + return new Promise(resolve => { this.inspectValuePromise = { resolve }; }); + } + attach(projectService: ProjectService) { this.projectService = projectService; if (this.logger.hasLevel(LogLevel.requestTime)) { @@ -320,7 +326,7 @@ namespace ts.server { this.send({ projectName: p.getProjectName(), kind: "closeProject" }); } - private send(rq: TypingInstallerRequestUnion): void { + private send(rq: T): void { this.installer.send(rq); } @@ -353,7 +359,7 @@ namespace ts.server { } } - private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { + private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | InspectValueResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Received response:${stringifyIndented(response)}`); } @@ -378,6 +384,10 @@ namespace ts.server { this.event(response, "setTypings"); break; } + case ActionValueInspected: + this.inspectValuePromise!.resolve(response.result); + this.inspectValuePromise = undefined; + break; case EventInitializationFailed: { const body: protocol.TypesInstallerInitializationFailedEventBody = { diff --git a/src/typingsInstaller/nodeTypingsInstaller.ts b/src/typingsInstaller/nodeTypingsInstaller.ts index d2c7269f9bf..00ee8b4fa19 100644 --- a/src/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/typingsInstaller/nodeTypingsInstaller.ts @@ -164,6 +164,11 @@ namespace ts.server.typingsInstaller { } break; } + case "inspectValue": { + const response: InspectValueResponse = { kind: ActionValueInspected, result: inspectModule(req.options.fileNameToRequire) }; + this.sendResponse(response); + break; + } default: Debug.assertNever(req); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index e9b896e9d17..21ee605120a 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4445,6 +4445,7 @@ declare namespace ts.server { type ActionSet = "action::set"; type ActionInvalidate = "action::invalidate"; type ActionPackageInstalled = "action::packageInstalled"; + type ActionValueInspected = "action::valueInspected"; type EventTypesRegistry = "event::typesRegistry"; type EventBeginInstallTypes = "event::beginInstallTypes"; type EventEndInstallTypes = "event::endInstallTypes"; @@ -4453,7 +4454,7 @@ declare namespace ts.server { " __sortedArrayBrand": any; } interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; } interface TypingInstallerRequestWithProjectName { readonly projectName: string; @@ -4661,6 +4662,7 @@ declare namespace ts { getCustomTransformers?(): CustomTransformers | undefined; isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; + writeFile?(fileName: string, content: string): void; } interface LanguageService { cleanupSemanticCache(): void; @@ -4718,9 +4720,9 @@ declare namespace ts { toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; - applyCodeActionCommand(action: CodeActionCommand): Promise; - applyCodeActionCommand(action: CodeActionCommand[]): Promise; - applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise; + applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; + applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; /** @deprecated `fileName` will be ignored */ @@ -4882,9 +4884,16 @@ declare namespace ts { changes: ReadonlyArray; commands?: ReadonlyArray; } - type CodeActionCommand = InstallPackageAction; + type CodeActionCommand = InstallPackageAction | GenerateTypesAction; interface InstallPackageAction { } + interface GenerateTypesAction extends GenerateTypesOptions { + } + interface GenerateTypesOptions { + readonly file: string; + readonly fileToGenerateTypesFor: string; + readonly outputFileName: string; + } /** * A set of one or more available refactoring actions, grouped under a parent refactoring. */ @@ -8102,6 +8111,7 @@ declare namespace ts.server { useCaseSensitiveFileNames(): boolean; readDirectory(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; readFile(fileName: string): string | undefined; + writeFile(fileName: string, content: string): void; fileExists(file: string): boolean; resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModuleFull[]; getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index cdc5017209a..4b01738783d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4445,6 +4445,7 @@ declare namespace ts.server { type ActionSet = "action::set"; type ActionInvalidate = "action::invalidate"; type ActionPackageInstalled = "action::packageInstalled"; + type ActionValueInspected = "action::valueInspected"; type EventTypesRegistry = "event::typesRegistry"; type EventBeginInstallTypes = "event::beginInstallTypes"; type EventEndInstallTypes = "event::endInstallTypes"; @@ -4453,7 +4454,7 @@ declare namespace ts.server { " __sortedArrayBrand": any; } interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; } interface TypingInstallerRequestWithProjectName { readonly projectName: string; @@ -4661,6 +4662,7 @@ declare namespace ts { getCustomTransformers?(): CustomTransformers | undefined; isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; + writeFile?(fileName: string, content: string): void; } interface LanguageService { cleanupSemanticCache(): void; @@ -4718,9 +4720,9 @@ declare namespace ts { toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; - applyCodeActionCommand(action: CodeActionCommand): Promise; - applyCodeActionCommand(action: CodeActionCommand[]): Promise; - applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise; + applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; + applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; /** @deprecated `fileName` will be ignored */ @@ -4882,9 +4884,16 @@ declare namespace ts { changes: ReadonlyArray; commands?: ReadonlyArray; } - type CodeActionCommand = InstallPackageAction; + type CodeActionCommand = InstallPackageAction | GenerateTypesAction; interface InstallPackageAction { } + interface GenerateTypesAction extends GenerateTypesOptions { + } + interface GenerateTypesOptions { + readonly file: string; + readonly fileToGenerateTypesFor: string; + readonly outputFileName: string; + } /** * A set of one or more available refactoring actions, grouped under a parent refactoring. */ diff --git a/tests/baselines/reference/generateTypes/global.d.ts b/tests/baselines/reference/generateTypes/global.d.ts new file mode 100644 index 00000000000..a49c80258ae --- /dev/null +++ b/tests/baselines/reference/generateTypes/global.d.ts @@ -0,0 +1,236 @@ +export class Array { + static from(p0: any): any; + static isArray(p0: any): any; + static of(): any; + concat(p0: any): any; + copyWithin(p0: any, p1: any): any; + entries(): any; + every(p0: any): any; + fill(p0: any): any; + filter(p0: any): any; + find(p0: any): any; + findIndex(p0: any): any; + forEach(p0: any): any; + includes(p0: any): any; + indexOf(p0: any): any; + join(p0: any): any; + keys(): any; + lastIndexOf(p0: any): any; + map(p0: any): any; + pop(): any; + push(p0: any): any; + reduce(p0: any): any; + reduceRight(p0: any): any; + reverse(): any; + shift(): any; + slice(p0: any, p1: any): any; + some(p0: any): any; + sort(p0: any): any; + splice(p0: any, p1: any): any; + toLocaleString(): any; + unshift(p0: any): any; +} +export class Boolean { + constructor(p0: any); + valueOf(): any; +} +export class Date { + static UTC(p0: any, p1: any, p2: any, p3: any, p4: any, p5: any, p6: any): any; + static now(): any; + static parse(p0: any): any; + constructor(p0: any, p1: any, p2: any, p3: any, p4: any, p5: any, p6: any); + getDate(): any; + getDay(): any; + getFullYear(): any; + getHours(): any; + getMilliseconds(): any; + getMinutes(): any; + getMonth(): any; + getSeconds(): any; + getTime(): any; + getTimezoneOffset(): any; + getUTCDate(): any; + getUTCDay(): any; + getUTCFullYear(): any; + getUTCHours(): any; + getUTCMilliseconds(): any; + getUTCMinutes(): any; + getUTCMonth(): any; + getUTCSeconds(): any; + getYear(): any; + setDate(p0: any): any; + setFullYear(p0: any, p1: any, p2: any): any; + setHours(p0: any, p1: any, p2: any, p3: any): any; + setMilliseconds(p0: any): any; + setMinutes(p0: any, p1: any, p2: any): any; + setMonth(p0: any, p1: any): any; + setSeconds(p0: any, p1: any): any; + setTime(p0: any): any; + setUTCDate(p0: any): any; + setUTCFullYear(p0: any, p1: any, p2: any): any; + setUTCHours(p0: any, p1: any, p2: any, p3: any): any; + setUTCMilliseconds(p0: any): any; + setUTCMinutes(p0: any, p1: any, p2: any): any; + setUTCMonth(p0: any, p1: any): any; + setUTCSeconds(p0: any, p1: any): any; + setYear(p0: any): any; + toDateString(): any; + toGMTString(): any; + toISOString(): any; + toJSON(p0: any): any; + toLocaleDateString(): any; + toLocaleString(): any; + toLocaleTimeString(): any; + toTimeString(): any; + toUTCString(): any; + valueOf(): any; +} +export namespace Math { + const E: number; + const LN10: number; + const LN2: number; + const LOG10E: number; + const LOG2E: number; + const PI: number; + const SQRT1_2: number; + const SQRT2: number; + function abs(p0: any): any; + function acos(p0: any): any; + function acosh(p0: any): any; + function asin(p0: any): any; + function asinh(p0: any): any; + function atan(p0: any): any; + function atan2(p0: any, p1: any): any; + function atanh(p0: any): any; + function cbrt(p0: any): any; + function ceil(p0: any): any; + function clz32(p0: any): any; + function cos(p0: any): any; + function cosh(p0: any): any; + function exp(p0: any): any; + function expm1(p0: any): any; + function floor(p0: any): any; + function fround(p0: any): any; + function hypot(p0: any, p1: any): any; + function imul(p0: any, p1: any): any; + function log(p0: any): any; + function log10(p0: any): any; + function log1p(p0: any): any; + function log2(p0: any): any; + function max(p0: any, p1: any): any; + function min(p0: any, p1: any): any; + function pow(p0: any, p1: any): any; + function random(): any; + function round(p0: any): any; + function sign(p0: any): any; + function sin(p0: any): any; + function sinh(p0: any): any; + function sqrt(p0: any): any; + function tan(p0: any): any; + function tanh(p0: any): any; + function trunc(p0: any): any; +} +export class Number { + static EPSILON: number; + static MAX_SAFE_INTEGER: number; + static MAX_VALUE: number; + static MIN_SAFE_INTEGER: number; + static MIN_VALUE: number; + static NEGATIVE_INFINITY: number; + static NaN: number; + static POSITIVE_INFINITY: number; + static isFinite(p0: any): any; + static isInteger(p0: any): any; + static isNaN(p0: any): any; + static isSafeInteger(p0: any): any; + static parseFloat(p0: any): any; + static parseInt(p0: any, p1: any): any; + constructor(p0: any); + toExponential(p0: any): any; + toFixed(p0: any): any; + toLocaleString(): any; + toPrecision(p0: any): any; + toString(p0: any): any; + valueOf(): any; +} +export class RegExp { + static $1: any; + static $2: any; + static $3: any; + static $4: any; + static $5: any; + static $6: any; + static $7: any; + static $8: any; + static $9: any; + static $_: any; + static input: any; + static lastMatch: any; + static lastParen: any; + static leftContext: any; + static rightContext: any; + constructor(p0: any, p1: any); + compile(p0: any, p1: any): any; + exec(p0: any): any; + test(p0: any): any; +} +export class String { + static fromCharCode(p0: any): any; + static fromCodePoint(p0: any): any; + static raw(p0: any): any; + anchor(p0: any): any; + big(): any; + blink(): any; + bold(): any; + charAt(p0: any): any; + charCodeAt(p0: any): any; + codePointAt(p0: any): any; + concat(p0: any): any; + endsWith(p0: any): any; + fixed(): any; + fontcolor(p0: any): any; + fontsize(p0: any): any; + includes(p0: any): any; + indexOf(p0: any): any; + italics(): any; + lastIndexOf(p0: any): any; + link(p0: any): any; + localeCompare(p0: any): any; + match(p0: any): any; + normalize(): any; + repeat(p0: any): any; + replace(p0: any, p1: any): any; + search(p0: any): any; + slice(p0: any, p1: any): any; + small(): any; + split(p0: any, p1: any): any; + startsWith(p0: any): any; + strike(): any; + sub(): any; + substr(p0: any, p1: any): any; + substring(p0: any, p1: any): any; + sup(): any; + toLocaleLowerCase(): any; + toLocaleUpperCase(): any; + toLowerCase(): any; + toUpperCase(): any; + trim(): any; + trimLeft(): any; + trimRight(): any; + valueOf(): any; +} +export class Symbol { + static hasInstance: symbol; + static isConcatSpreadable: symbol; + static iterator: symbol; + static keyFor(p0: any): any; + static match: symbol; + static replace: symbol; + static search: symbol; + static species: symbol; + static split: symbol; + static toPrimitive: symbol; + static toStringTag: symbol; + static unscopables: symbol; + valueOf(): any; +} \ No newline at end of file diff --git a/tests/baselines/reference/generateTypes/lodash.d.ts b/tests/baselines/reference/generateTypes/lodash.d.ts new file mode 100644 index 00000000000..6354df710db --- /dev/null +++ b/tests/baselines/reference/generateTypes/lodash.d.ts @@ -0,0 +1,668 @@ +export = example; +declare class example { + static VERSION: string; + static add(value: any, other: any): any; + static after(n: any, func: any): any; + static ary(func: any, n: any, guard: any): any; + static assign(...args: any[]): any; + static assignIn(...args: any[]): any; + static assignInWith(...args: any[]): any; + static assignWith(...args: any[]): any; + static at(...args: any[]): any; + static attempt(...args: any[]): any; + static before(n: any, func: any): any; + static bindAll(...args: any[]): any; + static camelCase(string: any): any; + static capitalize(string: any): any; + static castArray(...args: any[]): any; + static ceil(number: any, precision: any): any; + static chain(value: any): any; + static chunk(array: any, size: any, guard: any): any; + static clamp(number: any, lower: any, upper: any): any; + static clone(value: any): any; + static cloneDeep(value: any): any; + static cloneDeepWith(value: any, customizer: any): any; + static cloneWith(value: any, customizer: any): any; + static compact(array: any): any; + static concat(...args: any[]): any; + static cond(pairs: any): any; + static conforms(source: any): any; + static conformsTo(object: any, source: any): any; + static constant(value: any): any; + static countBy(collection: any, iteratee: any): any; + static create(prototype: any, properties: any): any; + static debounce(func: any, wait: any, options: any): any; + static deburr(string: any): any; + static defaultTo(value: any, defaultValue: any): any; + static defaults(...args: any[]): any; + static defaultsDeep(...args: any[]): any; + static defer(...args: any[]): any; + static delay(...args: any[]): any; + static difference(...args: any[]): any; + static differenceBy(...args: any[]): any; + static differenceWith(...args: any[]): any; + static divide(value: any, other: any): any; + static drop(array: any, n: any, guard: any): any; + static dropRight(array: any, n: any, guard: any): any; + static dropRightWhile(array: any, predicate: any): any; + static dropWhile(array: any, predicate: any): any; + static each(collection: any, iteratee: any): any; + static eachRight(collection: any, iteratee: any): any; + static endsWith(string: any, target: any, position: any): any; + static entries(object: any): any; + static entriesIn(object: any): any; + static eq(value: any, other: any): any; + static escape(string: any): any; + static escapeRegExp(string: any): any; + static every(collection: any, predicate: any, guard: any): any; + static extend(...args: any[]): any; + static extendWith(...args: any[]): any; + static fill(array: any, value: any, start: any, end: any): any; + static filter(collection: any, predicate: any): any; + static find(collection: any, predicate: any, fromIndex: any): any; + static findIndex(array: any, predicate: any, fromIndex: any): any; + static findKey(object: any, predicate: any): any; + static findLast(collection: any, predicate: any, fromIndex: any): any; + static findLastIndex(array: any, predicate: any, fromIndex: any): any; + static findLastKey(object: any, predicate: any): any; + static first(array: any): any; + static flatMap(collection: any, iteratee: any): any; + static flatMapDeep(collection: any, iteratee: any): any; + static flatMapDepth(collection: any, iteratee: any, depth: any): any; + static flatten(array: any): any; + static flattenDeep(array: any): any; + static flattenDepth(array: any, depth: any): any; + static flip(func: any): any; + static floor(number: any, precision: any): any; + static flow(...args: any[]): any; + static flowRight(...args: any[]): any; + static forEach(collection: any, iteratee: any): any; + static forEachRight(collection: any, iteratee: any): any; + static forIn(object: any, iteratee: any): any; + static forInRight(object: any, iteratee: any): any; + static forOwn(object: any, iteratee: any): any; + static forOwnRight(object: any, iteratee: any): any; + static fromPairs(pairs: any): any; + static functions(object: any): any; + static functionsIn(object: any): any; + static get(object: any, path: any, defaultValue: any): any; + static groupBy(collection: any, iteratee: any): any; + static gt(value: any, other: any): any; + static gte(value: any, other: any): any; + static has(object: any, path: any): any; + static hasIn(object: any, path: any): any; + static head(array: any): any; + static identity(value: any): any; + static inRange(number: any, start: any, end: any): any; + static includes(collection: any, value: any, fromIndex: any, guard: any): any; + static indexOf(array: any, value: any, fromIndex: any): any; + static initial(array: any): any; + static intersection(...args: any[]): any; + static intersectionBy(...args: any[]): any; + static intersectionWith(...args: any[]): any; + static invert(object: any, iteratee: any): any; + static invertBy(object: any, iteratee: any): any; + static invoke(...args: any[]): any; + static invokeMap(...args: any[]): any; + static isArguments(value: any): any; + static isArray(p0: any): any; + static isArrayBuffer(value: any): any; + static isArrayLike(value: any): any; + static isArrayLikeObject(value: any): any; + static isBoolean(value: any): any; + static isBuffer(b: any): any; + static isDate(value: any): any; + static isElement(value: any): any; + static isEmpty(value: any): any; + static isEqual(value: any, other: any): any; + static isEqualWith(value: any, other: any, customizer: any): any; + static isError(value: any): any; + static isFinite(value: any): any; + static isFunction(value: any): any; + static isInteger(value: any): any; + static isLength(value: any): any; + static isMap(value: any): any; + static isMatch(object: any, source: any): any; + static isMatchWith(object: any, source: any, customizer: any): any; + static isNaN(value: any): any; + static isNative(value: any): any; + static isNil(value: any): any; + static isNull(value: any): any; + static isNumber(value: any): any; + static isObject(value: any): any; + static isObjectLike(value: any): any; + static isPlainObject(value: any): any; + static isRegExp(value: any): any; + static isSafeInteger(value: any): any; + static isSet(value: any): any; + static isString(value: any): any; + static isSymbol(value: any): any; + static isTypedArray(value: any): any; + static isUndefined(value: any): any; + static isWeakMap(value: any): any; + static isWeakSet(value: any): any; + static iteratee(func: any): any; + static join(array: any, separator: any): any; + static kebabCase(string: any): any; + static keyBy(collection: any, iteratee: any): any; + static keys(object: any): any; + static keysIn(object: any): any; + static last(array: any): any; + static lastIndexOf(array: any, value: any, fromIndex: any): any; + static lowerCase(string: any): any; + static lowerFirst(string: any): any; + static lt(value: any, other: any): any; + static lte(value: any, other: any): any; + static map(collection: any, iteratee: any): any; + static mapKeys(object: any, iteratee: any): any; + static mapValues(object: any, iteratee: any): any; + static matches(source: any): any; + static matchesProperty(path: any, srcValue: any): any; + static max(array: any): any; + static maxBy(array: any, iteratee: any): any; + static mean(array: any): any; + static meanBy(array: any, iteratee: any): any; + static merge(...args: any[]): any; + static mergeWith(...args: any[]): any; + static method(...args: any[]): any; + static methodOf(...args: any[]): any; + static min(array: any): any; + static minBy(array: any, iteratee: any): any; + static mixin(object: any, source: any, options: any): any; + static multiply(value: any, other: any): any; + static negate(predicate: any): any; + static noConflict(): any; + static noop(): void; + static now(): any; + static nth(array: any, n: any): any; + static nthArg(n: any): any; + static omit(...args: any[]): any; + static omitBy(object: any, predicate: any): any; + static once(func: any): any; + static orderBy(collection: any, iteratees: any, orders: any, guard: any): any; + static over(...args: any[]): any; + static overArgs(...args: any[]): any; + static overEvery(...args: any[]): any; + static overSome(...args: any[]): any; + static pad(string: any, length: any, chars: any): any; + static padEnd(string: any, length: any, chars: any): any; + static padStart(string: any, length: any, chars: any): any; + static parseInt(string: any, radix: any, guard: any): any; + static partition(collection: any, iteratee: any): any; + static pick(...args: any[]): any; + static pickBy(object: any, predicate: any): any; + static property(path: any): any; + static propertyOf(object: any): any; + static pull(...args: any[]): any; + static pullAll(array: any, values: any): any; + static pullAllBy(array: any, values: any, iteratee: any): any; + static pullAllWith(array: any, values: any, comparator: any): any; + static pullAt(...args: any[]): any; + static random(lower: any, upper: any, floating: any): any; + static range(start: any, end: any, step: any): any; + static rangeRight(start: any, end: any, step: any): any; + static rearg(...args: any[]): any; + static reduce(collection: any, iteratee: any, accumulator: any, ...args: any[]): any; + static reduceRight(collection: any, iteratee: any, accumulator: any, ...args: any[]): any; + static reject(collection: any, predicate: any): any; + static remove(array: any, predicate: any): any; + static repeat(string: any, n: any, guard: any): any; + static replace(...args: any[]): any; + static rest(func: any, start: any): any; + static result(object: any, path: any, defaultValue: any): any; + static reverse(array: any): any; + static round(number: any, precision: any): any; + static runInContext(context: any): any; + static sample(collection: any): any; + static sampleSize(collection: any, n: any, guard: any): any; + static set(object: any, path: any, value: any): any; + static setWith(object: any, path: any, value: any, customizer: any): any; + static shuffle(collection: any): any; + static size(collection: any): any; + static slice(array: any, start: any, end: any): any; + static snakeCase(string: any): any; + static some(collection: any, predicate: any, guard: any): any; + static sortBy(...args: any[]): any; + static sortedIndex(array: any, value: any): any; + static sortedIndexBy(array: any, value: any, iteratee: any): any; + static sortedIndexOf(array: any, value: any): any; + static sortedLastIndex(array: any, value: any): any; + static sortedLastIndexBy(array: any, value: any, iteratee: any): any; + static sortedLastIndexOf(array: any, value: any): any; + static sortedUniq(array: any): any; + static sortedUniqBy(array: any, iteratee: any): any; + static split(string: any, separator: any, limit: any): any; + static spread(func: any, start: any): any; + static startCase(string: any): any; + static startsWith(string: any, target: any, position: any): any; + static stubArray(): any; + static stubFalse(): any; + static stubObject(): any; + static stubString(): any; + static stubTrue(): any; + static subtract(value: any, other: any): any; + static sum(array: any): any; + static sumBy(array: any, iteratee: any): any; + static tail(array: any): any; + static take(array: any, n: any, guard: any): any; + static takeRight(array: any, n: any, guard: any): any; + static takeRightWhile(array: any, predicate: any): any; + static takeWhile(array: any, predicate: any): any; + static tap(value: any, interceptor: any): any; + static template(string: any, options: any, guard: any): any; + static templateSettings: { + escape: RegExp; + evaluate: RegExp; + imports: {}; + interpolate: RegExp; + variable: string; + }; + static throttle(func: any, wait: any, options: any): any; + static thru(value: any, interceptor: any): any; + static times(n: any, iteratee: any): any; + static toArray(value: any): any; + static toFinite(value: any): any; + static toInteger(value: any): any; + static toLength(value: any): any; + static toLower(value: any): any; + static toNumber(value: any): any; + static toPairs(object: any): any; + static toPairsIn(object: any): any; + static toPath(value: any): any; + static toPlainObject(value: any): any; + static toSafeInteger(value: any): any; + static toString(value: any): any; + static toUpper(value: any): any; + static transform(object: any, iteratee: any, accumulator: any): any; + static trim(string: any, chars: any, guard: any): any; + static trimEnd(string: any, chars: any, guard: any): any; + static trimStart(string: any, chars: any, guard: any): any; + static truncate(string: any, options: any): any; + static unary(func: any): any; + static unescape(string: any): any; + static union(...args: any[]): any; + static unionBy(...args: any[]): any; + static unionWith(...args: any[]): any; + static uniq(array: any): any; + static uniqBy(array: any, iteratee: any): any; + static uniqWith(array: any, comparator: any): any; + static uniqueId(prefix: any): any; + static unset(object: any, path: any): any; + static unzip(array: any): any; + static unzipWith(array: any, iteratee: any): any; + static update(object: any, path: any, updater: any): any; + static updateWith(object: any, path: any, updater: any, customizer: any): any; + static upperCase(string: any): any; + static upperFirst(string: any): any; + static values(object: any): any; + static valuesIn(object: any): any; + static without(...args: any[]): any; + static words(string: any, pattern: any, guard: any): any; + static wrap(value: any, wrapper: any): any; + static xor(...args: any[]): any; + static xorBy(...args: any[]): any; + static xorWith(...args: any[]): any; + static zip(...args: any[]): any; + static zipObject(props: any, values: any): any; + static zipObjectDeep(props: any, values: any): any; + static zipWith(...args: any[]): any; + constructor(value: any); + add(...args: any[]): any; + after(...args: any[]): any; + ary(...args: any[]): any; + assign(...args: any[]): any; + assignIn(...args: any[]): any; + assignInWith(...args: any[]): any; + assignWith(...args: any[]): any; + at(...args: any[]): any; + attempt(...args: any[]): any; + before(...args: any[]): any; + bind(...args: any[]): any; + bindAll(...args: any[]): any; + bindKey(...args: any[]): any; + camelCase(...args: any[]): any; + capitalize(...args: any[]): any; + castArray(...args: any[]): any; + ceil(...args: any[]): any; + chain(): any; + chunk(...args: any[]): any; + clamp(...args: any[]): any; + clone(...args: any[]): any; + cloneDeep(...args: any[]): any; + cloneDeepWith(...args: any[]): any; + cloneWith(...args: any[]): any; + commit(): any; + compact(...args: any[]): any; + concat(...args: any[]): any; + cond(...args: any[]): any; + conforms(...args: any[]): any; + conformsTo(...args: any[]): any; + constant(...args: any[]): any; + countBy(...args: any[]): any; + create(...args: any[]): any; + curry(...args: any[]): any; + curryRight(...args: any[]): any; + debounce(...args: any[]): any; + deburr(...args: any[]): any; + defaultTo(...args: any[]): any; + defaults(...args: any[]): any; + defaultsDeep(...args: any[]): any; + defer(...args: any[]): any; + delay(...args: any[]): any; + difference(...args: any[]): any; + differenceBy(...args: any[]): any; + differenceWith(...args: any[]): any; + divide(...args: any[]): any; + drop(...args: any[]): any; + dropRight(...args: any[]): any; + dropRightWhile(...args: any[]): any; + dropWhile(...args: any[]): any; + each(...args: any[]): any; + eachRight(...args: any[]): any; + endsWith(...args: any[]): any; + entries(...args: any[]): any; + entriesIn(...args: any[]): any; + eq(...args: any[]): any; + escape(...args: any[]): any; + escapeRegExp(...args: any[]): any; + every(...args: any[]): any; + extend(...args: any[]): any; + extendWith(...args: any[]): any; + fill(...args: any[]): any; + filter(...args: any[]): any; + find(...args: any[]): any; + findIndex(...args: any[]): any; + findKey(...args: any[]): any; + findLast(...args: any[]): any; + findLastIndex(...args: any[]): any; + findLastKey(...args: any[]): any; + first(...args: any[]): any; + flatMap(...args: any[]): any; + flatMapDeep(...args: any[]): any; + flatMapDepth(...args: any[]): any; + flatten(...args: any[]): any; + flattenDeep(...args: any[]): any; + flattenDepth(...args: any[]): any; + flip(...args: any[]): any; + floor(...args: any[]): any; + flow(...args: any[]): any; + flowRight(...args: any[]): any; + forEach(...args: any[]): any; + forEachRight(...args: any[]): any; + forIn(...args: any[]): any; + forInRight(...args: any[]): any; + forOwn(...args: any[]): any; + forOwnRight(...args: any[]): any; + fromPairs(...args: any[]): any; + functions(...args: any[]): any; + functionsIn(...args: any[]): any; + get(...args: any[]): any; + groupBy(...args: any[]): any; + gt(...args: any[]): any; + gte(...args: any[]): any; + has(...args: any[]): any; + hasIn(...args: any[]): any; + head(...args: any[]): any; + identity(...args: any[]): any; + inRange(...args: any[]): any; + includes(...args: any[]): any; + indexOf(...args: any[]): any; + initial(...args: any[]): any; + intersection(...args: any[]): any; + intersectionBy(...args: any[]): any; + intersectionWith(...args: any[]): any; + invert(...args: any[]): any; + invertBy(...args: any[]): any; + invoke(...args: any[]): any; + invokeMap(...args: any[]): any; + isArguments(...args: any[]): any; + isArray(...args: any[]): any; + isArrayBuffer(...args: any[]): any; + isArrayLike(...args: any[]): any; + isArrayLikeObject(...args: any[]): any; + isBoolean(...args: any[]): any; + isBuffer(...args: any[]): any; + isDate(...args: any[]): any; + isElement(...args: any[]): any; + isEmpty(...args: any[]): any; + isEqual(...args: any[]): any; + isEqualWith(...args: any[]): any; + isError(...args: any[]): any; + isFinite(...args: any[]): any; + isFunction(...args: any[]): any; + isInteger(...args: any[]): any; + isLength(...args: any[]): any; + isMap(...args: any[]): any; + isMatch(...args: any[]): any; + isMatchWith(...args: any[]): any; + isNaN(...args: any[]): any; + isNative(...args: any[]): any; + isNil(...args: any[]): any; + isNull(...args: any[]): any; + isNumber(...args: any[]): any; + isObject(...args: any[]): any; + isObjectLike(...args: any[]): any; + isPlainObject(...args: any[]): any; + isRegExp(...args: any[]): any; + isSafeInteger(...args: any[]): any; + isSet(...args: any[]): any; + isString(...args: any[]): any; + isSymbol(...args: any[]): any; + isTypedArray(...args: any[]): any; + isUndefined(...args: any[]): any; + isWeakMap(...args: any[]): any; + isWeakSet(...args: any[]): any; + iteratee(...args: any[]): any; + join(...args: any[]): any; + kebabCase(...args: any[]): any; + keyBy(...args: any[]): any; + keys(...args: any[]): any; + keysIn(...args: any[]): any; + last(...args: any[]): any; + lastIndexOf(...args: any[]): any; + lowerCase(...args: any[]): any; + lowerFirst(...args: any[]): any; + lt(...args: any[]): any; + lte(...args: any[]): any; + map(...args: any[]): any; + mapKeys(...args: any[]): any; + mapValues(...args: any[]): any; + matches(...args: any[]): any; + matchesProperty(...args: any[]): any; + max(...args: any[]): any; + maxBy(...args: any[]): any; + mean(...args: any[]): any; + meanBy(...args: any[]): any; + memoize(...args: any[]): any; + merge(...args: any[]): any; + mergeWith(...args: any[]): any; + method(...args: any[]): any; + methodOf(...args: any[]): any; + min(...args: any[]): any; + minBy(...args: any[]): any; + mixin(...args: any[]): any; + multiply(...args: any[]): any; + negate(...args: any[]): any; + next(): any; + noConflict(...args: any[]): any; + noop(...args: any[]): any; + now(...args: any[]): any; + nth(...args: any[]): any; + nthArg(...args: any[]): any; + omit(...args: any[]): any; + omitBy(...args: any[]): any; + once(...args: any[]): any; + orderBy(...args: any[]): any; + over(...args: any[]): any; + overArgs(...args: any[]): any; + overEvery(...args: any[]): any; + overSome(...args: any[]): any; + pad(...args: any[]): any; + padEnd(...args: any[]): any; + padStart(...args: any[]): any; + parseInt(...args: any[]): any; + partial(...args: any[]): any; + partialRight(...args: any[]): any; + partition(...args: any[]): any; + pick(...args: any[]): any; + pickBy(...args: any[]): any; + plant(value: any): any; + pop(...args: any[]): any; + property(...args: any[]): any; + propertyOf(...args: any[]): any; + pull(...args: any[]): any; + pullAll(...args: any[]): any; + pullAllBy(...args: any[]): any; + pullAllWith(...args: any[]): any; + pullAt(...args: any[]): any; + push(...args: any[]): any; + random(...args: any[]): any; + range(...args: any[]): any; + rangeRight(...args: any[]): any; + rearg(...args: any[]): any; + reduce(...args: any[]): any; + reduceRight(...args: any[]): any; + reject(...args: any[]): any; + remove(...args: any[]): any; + repeat(...args: any[]): any; + replace(...args: any[]): any; + rest(...args: any[]): any; + result(...args: any[]): any; + reverse(): any; + round(...args: any[]): any; + runInContext(...args: any[]): any; + sample(...args: any[]): any; + sampleSize(...args: any[]): any; + set(...args: any[]): any; + setWith(...args: any[]): any; + shift(...args: any[]): any; + shuffle(...args: any[]): any; + size(...args: any[]): any; + slice(...args: any[]): any; + snakeCase(...args: any[]): any; + some(...args: any[]): any; + sort(...args: any[]): any; + sortBy(...args: any[]): any; + sortedIndex(...args: any[]): any; + sortedIndexBy(...args: any[]): any; + sortedIndexOf(...args: any[]): any; + sortedLastIndex(...args: any[]): any; + sortedLastIndexBy(...args: any[]): any; + sortedLastIndexOf(...args: any[]): any; + sortedUniq(...args: any[]): any; + sortedUniqBy(...args: any[]): any; + splice(...args: any[]): any; + split(...args: any[]): any; + spread(...args: any[]): any; + startCase(...args: any[]): any; + startsWith(...args: any[]): any; + stubArray(...args: any[]): any; + stubFalse(...args: any[]): any; + stubObject(...args: any[]): any; + stubString(...args: any[]): any; + stubTrue(...args: any[]): any; + subtract(...args: any[]): any; + sum(...args: any[]): any; + sumBy(...args: any[]): any; + tail(...args: any[]): any; + take(...args: any[]): any; + takeRight(...args: any[]): any; + takeRightWhile(...args: any[]): any; + takeWhile(...args: any[]): any; + tap(...args: any[]): any; + template(...args: any[]): any; + throttle(...args: any[]): any; + thru(...args: any[]): any; + times(...args: any[]): any; + toArray(...args: any[]): any; + toFinite(...args: any[]): any; + toInteger(...args: any[]): any; + toJSON(): any; + toLength(...args: any[]): any; + toLower(...args: any[]): any; + toNumber(...args: any[]): any; + toPairs(...args: any[]): any; + toPairsIn(...args: any[]): any; + toPath(...args: any[]): any; + toPlainObject(...args: any[]): any; + toSafeInteger(...args: any[]): any; + toUpper(...args: any[]): any; + transform(...args: any[]): any; + trim(...args: any[]): any; + trimEnd(...args: any[]): any; + trimStart(...args: any[]): any; + truncate(...args: any[]): any; + unary(...args: any[]): any; + unescape(...args: any[]): any; + union(...args: any[]): any; + unionBy(...args: any[]): any; + unionWith(...args: any[]): any; + uniq(...args: any[]): any; + uniqBy(...args: any[]): any; + uniqWith(...args: any[]): any; + uniqueId(...args: any[]): any; + unset(...args: any[]): any; + unshift(...args: any[]): any; + unzip(...args: any[]): any; + unzipWith(...args: any[]): any; + update(...args: any[]): any; + updateWith(...args: any[]): any; + upperCase(...args: any[]): any; + upperFirst(...args: any[]): any; + value(): any; + valueOf(): any; + values(...args: any[]): any; + valuesIn(...args: any[]): any; + without(...args: any[]): any; + words(...args: any[]): any; + wrap(...args: any[]): any; + xor(...args: any[]): any; + xorBy(...args: any[]): any; + xorWith(...args: any[]): any; + zip(...args: any[]): any; + zipObject(...args: any[]): any; + zipObjectDeep(...args: any[]): any; + zipWith(...args: any[]): any; +} +declare namespace example { + function bind(...args: any[]): any; + namespace bind { + // Circular reference from example.bind + const placeholder: any; + } + function bindKey(...args: any[]): any; + namespace bindKey { + // Circular reference from example.bindKey + const placeholder: any; + } + function curry(func: any, arity: any, guard: any): any; + namespace curry { + // Circular reference from example.curry + const placeholder: any; + } + function curryRight(func: any, arity: any, guard: any): any; + namespace curryRight { + // Circular reference from example.curryRight + const placeholder: any; + } + function memoize(func: any, resolver: any): any; + namespace memoize { + class Cache { + constructor(entries: any); + clear(): void; + get(key: any): any; + has(key: any): any; + set(key: any, value: any): any; + } + } + function partial(...args: any[]): any; + namespace partial { + // Circular reference from example.partial + const placeholder: any; + } + function partialRight(...args: any[]): any; + namespace partialRight { + // Circular reference from example.partialRight + const placeholder: any; + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixCannotFindModule_all.ts b/tests/cases/fourslash/codeFixCannotFindModule_all.ts index 044d0c5deb0..1b1b36d13ad 100644 --- a/tests/cases/fourslash/codeFixCannotFindModule_all.ts +++ b/tests/cases/fourslash/codeFixCannotFindModule_all.ts @@ -21,12 +21,11 @@ test.setTypesRegistry({ goTo.marker(); verify.codeFixAll({ - fixId: "fixCannotFindModule", + fixId: "installTypesPackage", fixAllDescription: "Install all missing types packages", + newFileContent: {}, // no changes commands: [ { packageName: "@types/abs", file: "/a.ts", type: "install package" }, { packageName: "@types/zap", file: "/a.ts", type: "install package" }, ], - newFileContent: `import * as abs from "abs"; -import * as zap from "zap";` // unchanged }); diff --git a/tests/cases/fourslash/codeFixCannotFindModule_generateTypes.ts b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes.ts new file mode 100644 index 00000000000..af8707a9f81 --- /dev/null +++ b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes.ts @@ -0,0 +1,44 @@ +/// + +// @Filename: /dir/node_modules/plus/index.js +////module.exports = function plus(x, y) { return x + y; }; + +// @Filename: /dir/a.ts +////import plus = require("plus"); +////plus; + +// @Filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "paths": { +//// "nota": ["valid_pathmapping"], +//// dontCrash: 37, +//// "*": ["abc123"], +//// } +//// } +////} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Generate types for 'plus'", + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "*": ["types/*"], + "nota": ["valid_pathmapping"], + dontCrash: 37, + "*": ["abc123"], + } + } +}`, + }, + commands: [{ + type: "generate types", + file: "/dir/a.ts", + fileToGenerateTypesFor: "/dir/node_modules/plus/index.js", + outputFileName: "/dir/types/plus.d.ts", + }], +}); diff --git a/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_all.ts b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_all.ts new file mode 100644 index 00000000000..183ca3324a4 --- /dev/null +++ b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_all.ts @@ -0,0 +1,47 @@ +/// + +// @Filename: /dir/node_modules/plus/index.js +////module.exports = function plus(x, y) { return x + y; }; + +// @Filename: /dir/node_modules/times/index.js +////module.exports = function times(x, y) { return x * y; }; + +// @Filename: /dir/a.ts +////import plus = require("plus"); +////import times = require("times"); +////plus; + +// @Filename: /dir/tsconfig.json +////{ +//// "compilerOptions": {} +////} + +goTo.file("/dir/a.ts"); +verify.codeFixAll({ + fixAllDescription: "Generate types for all packages without types", + fixId: "generateTypes", + newFileContent: { + "/dir/tsconfig.json": +// TODO: GH#26618 +`{ + "compilerOptions": { + "baseUrl": ".", + "paths": { "*": ["types/*"] }, +} +}`, + }, + commands: [ + { + type: "generate types", + file: "/dir/a.ts", + fileToGenerateTypesFor: "/dir/node_modules/plus/index.js", + outputFileName: "/dir/types/plus.d.ts", + }, + { + type: "generate types", + file: "/dir/a.ts", + fileToGenerateTypesFor: "/dir/node_modules/times/index.js", + outputFileName: "/dir/types/times.d.ts", + }, + ], +}); diff --git a/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_noExistingCompilerOptions.ts b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_noExistingCompilerOptions.ts new file mode 100644 index 00000000000..99a22078143 --- /dev/null +++ b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_noExistingCompilerOptions.ts @@ -0,0 +1,28 @@ +/// + +// @Filename: /dir/node_modules/plus/index.js +////module.exports = function plus(x, y) { return x * y; }; + +// @Filename: /dir/a.ts +////import plus = require("plus"); +////plus; + +// @Filename: /dir/tsconfig.json +////{} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Generate types for 'plus'", + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { "baseUrl": ".", "paths": { "*": ["types/*"] } }, +}`, + }, + commands: [{ + type: "generate types", + file: "/dir/a.ts", + fileToGenerateTypesFor: "/dir/node_modules/plus/index.js", + outputFileName: "/dir/types/plus.d.ts", + }], +}); diff --git a/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_notForNonexistentPackage.ts b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_notForNonexistentPackage.ts new file mode 100644 index 00000000000..a4e6450e933 --- /dev/null +++ b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_notForNonexistentPackage.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: /a.ts +////import plus = require("plus"); +////plus; + +// @Filename: /tsconfig.json +////{ +//// "compilerOptions": {} +////} + +goTo.file("/a.ts"); +verify.codeFixAvailable([]); diff --git a/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_typesDirectoryExists.ts b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_typesDirectoryExists.ts new file mode 100644 index 00000000000..5c095f84ba7 --- /dev/null +++ b/tests/cases/fourslash/codeFixCannotFindModule_generateTypes_typesDirectoryExists.ts @@ -0,0 +1,30 @@ +/// + +// @Filename: /dir/node_modules/plus/index.js +////module.exports = function plus(x, y) { return x * y; }; + +// @Filename: /dir/a.ts +////import plus = require("plus"); +////plus; + +// @Filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "baseUrl": "base", +//// "paths": { +//// "*": ["myTypes/*"], +//// }, +//// }, +////} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Generate types for 'plus'", + newFileContent: {}, // no change + commands: [{ + type: "generate types", + file: "/dir/a.ts", + fileToGenerateTypesFor: "/dir/node_modules/plus/index.js", + outputFileName: "/dir/base/myTypes/plus.d.ts", + }], +}); diff --git a/tests/cases/fourslash/codeFixGenerateDefinitions.ts b/tests/cases/fourslash/codeFixGenerateDefinitions.ts new file mode 100644 index 00000000000..41dc24d3a3c --- /dev/null +++ b/tests/cases/fourslash/codeFixGenerateDefinitions.ts @@ -0,0 +1,9 @@ +/// + +// @Filename: /node_modules/foo/index.d.ts +////module.exports = 0; + +// @Filename: /a.ts +////import * as foo from "foo"; + +verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/codeFixUndeclaredMethodFunctionArgs.ts b/tests/cases/fourslash/codeFixUndeclaredMethodFunctionArgs.ts index 1389a50935b..478b2a7c647 100644 --- a/tests/cases/fourslash/codeFixUndeclaredMethodFunctionArgs.ts +++ b/tests/cases/fourslash/codeFixUndeclaredMethodFunctionArgs.ts @@ -28,5 +28,5 @@ verify.codeFix({ foo1(arg0: () => number, arg1: () => string, arg2: () => boolean): any { throw new Error("Method not implemented."); } - ` + `, }); diff --git a/tests/cases/fourslash/formatWithTabs.ts b/tests/cases/fourslash/formatWithTabs.ts index c33808bd26a..e1b8878f4a9 100644 --- a/tests/cases/fourslash/formatWithTabs.ts +++ b/tests/cases/fourslash/formatWithTabs.ts @@ -13,4 +13,4 @@ format.document(); verify.currentFileContentIs( `const foo = [ 1 -];`); \ No newline at end of file +];`); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index cf4752a65ab..e254b2b51db 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -284,7 +284,7 @@ declare namespace FourSlashInterface { docCommentTemplateAt(markerName: string | FourSlashInterface.Marker, expectedOffset: number, expectedText: string): void; noDocCommentTemplateAt(markerName: string | FourSlashInterface.Marker): void; rangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number): void; - codeFixAll(options: { fixId: string, fixAllDescription: string, newFileContent: string, commands?: {}[] }): void; + codeFixAll(options: { fixId: string, fixAllDescription: string, newFileContent: NewFileContent, commands?: {}[] }): void; fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, actionName: string, formattingOptions?: FormatCodeOptions): void; rangeIs(expectedText: string, includeWhiteSpace?: boolean): void; fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, formattingOptions?: FormatCodeOptions): void; @@ -348,6 +348,8 @@ declare namespace FourSlashInterface { readonly preferences?: UserPreferences; }): void; noMoveToNewFile(): void; + + generateTypes(...options: GenerateTypesOptions[]): void; } class edit { backspace(count?: number): void; @@ -637,6 +639,13 @@ declare namespace FourSlashInterface { readonly text: string | undefined; } + interface GenerateTypesOptions { + readonly name?: string; + readonly value: unknown; + readonly output?: string | undefined; + readonly outputBaseline?: string; + } + type ArrayOrSingle = T | ReadonlyArray; type NewFileContent = string | { readonly [fileName: string]: string }; } diff --git a/tests/cases/fourslash/generateTypes.ts b/tests/cases/fourslash/generateTypes.ts new file mode 100644 index 00000000000..bfe521e2046 --- /dev/null +++ b/tests/cases/fourslash/generateTypes.ts @@ -0,0 +1,109 @@ +/// + +////dummy text + +verify.generateTypes( +{ + value: 0, + output: +`export = example; +declare const example: number;`, +}, +{ + value: (x, y) => x + y, + output: +`export = example; +declare function example(x: any, y: any): void;`, +}, +{ + // non-arrow functions have different toString(), so important to test + value: function(x, y) { + return x * y; + function inner() { + arguments; // Should not affect type inference + } + }, + output: +`export = example; +declare function example(x: any, y: any): any;`, +}, +{ + value: function(x) { arguments; }, + output: +`export = example; +declare function example(x: any, ...args: any[]): void;`, +}, + +{ + value: ({ default() {} }), + output: +`export default function _default(): void;`, +}, + +{ + value: ({ default: class {} }), + output: +`export default class _default { +}`, +}, + +{ + value: new Date(), + output: +`export = example; +declare const example: Date;`, +}, + +{ + value: [0], + output: +`export = example; +declare const example: number[];`, +}, +{ + value: [() => 0, () => ""], + output: +`export = example; +declare const example: Function[];`, +}, +{ + value: (() => { + const a = []; + a.push(a); + return a; + })(), + output: +`export = example; +declare const example: any[];`, +}, +{ + value: (() => { + const o = { + default: 0, + a: 0, + b: "", + self: null, + fn: x => x, + ns1: { x: 0, default: 0 }, + ns2: { fn: x => x, default: 0 }, + }; + o.self = o; + return o; + })(), + output: +`export const a: number; +export const b: string; +export default _default; +export const _default: number; +export function fn(x: any): void; +export const ns1: { + default: number; + x: number; +}; +export namespace ns2 { + function fn(x: any): void; +} +// Circular reference from example +export const self: any;`, +}, +); diff --git a/tests/cases/fourslash/generateTypes_baselines.ts b/tests/cases/fourslash/generateTypes_baselines.ts new file mode 100644 index 00000000000..a8363b30283 --- /dev/null +++ b/tests/cases/fourslash/generateTypes_baselines.ts @@ -0,0 +1,35 @@ +/// + +////dummy text + +verify.generateTypes( + // would like to test against the real "global" but that may vary between node versions. + { + value: { + Array: ignore(Array, ["values"]), + Boolean, + Date, + Math, + Number, + RegExp, + String: ignore(String, ["padStart", "padEnd", "trimStart", "trimEnd"]), + Symbol: ignore(Symbol, ["asyncIterator"]), + }, + outputBaseline: "global", + }, + { value: require("lodash"), outputBaseline: "lodash" }, +); + +// Ignore properties only present in newer versions of node. +function ignore(Cls: Function, ignored: ReadonlyArray): Function { + class Copy {} + for (const name of Object.getOwnPropertyNames(Cls)) { + if (ignored.includes(name) || name === "arguments" || name === "caller" || name === "name" || name === "length" || name === "prototype") continue; + Copy[name] = Cls[name]; + } + for (const name of Object.getOwnPropertyNames(Cls.prototype)) { + if (ignored.includes(name)) continue; + Copy.prototype[name] = Cls.prototype[name]; + } + return Copy; +} diff --git a/tests/cases/fourslash/generateTypes_classes.ts b/tests/cases/fourslash/generateTypes_classes.ts new file mode 100644 index 00000000000..94fd43fe529 --- /dev/null +++ b/tests/cases/fourslash/generateTypes_classes.ts @@ -0,0 +1,109 @@ +/// + +////dummy text + +verify.generateTypes( +{ + value: class {}, + output: +`export = example; +declare class example { +}`, +}, + +{ + value: class { + constructor(x) { + (this as any).x = x; + // Code inside this function should be ignored + function f(this: any) { + this.y = 0; + } + // Same for this class + class Other { constructor() { (this as any).z = 0; } } + } + }, + output: +`export = example; +declare class example { + constructor(x: any); + x: any; +}`, +}, +{ + value: { x: 0, export: 0 }, + output: `export const x: number;`, +}, +{ + value: (() => { + class Super { + superField = 0; // TODO: climb to prototype.constructor and get instance fields? + superMethod() {} + static superStaticMethod() {} + } + class C extends Super { + constructor() { + super(); + (this as any)._privateField = 0; + (this as any).field = 0; + } + + _privateMethod() {} + method(_p) { + (this as any).otherField = 0; // TODO: include this in output? + } + + static _privateStatic() {} + static staticMethod(_s: any) {} + static staticMethodWithNoNamespaceMembers(_p: any) {} + + static _privateStaticField = 0; + static staticField = 0; + static innerClass = class {}; + } + (C.prototype as any).prototypeNonFunction = 0; // ignored + (C.staticMethod as any).staticMethodProperty = 0; + (C.staticMethod as any)._staticFieldPrivateMember = 0; + (C.prototype.method as any).methodMember = 0; // ignored + // Non-identifier names should be ignored. + (C as any)["&"] = function() {}; + (C.prototype as any)["&"] = function() {}; + return C; + })(), + output: +`export = example; +declare class example { + static staticField: number; + static staticMethodWithNoNamespaceMembers(_p: any): void; + static superStaticMethod(): void; + field: any; + method(_p: any): void; + superMethod(): void; +} +declare namespace example { + class innerClass { + } + function staticMethod(_s: any): void; + namespace staticMethod { + const staticMethodProperty: number; + } +}`, +}, + +{ + value: (() => { + function F() { this.x = 0; } + (F as any).staticMethod = function() {} + F.prototype.method = function() { } + return F; + })(), + output: +`export = example; +declare class example { + static staticMethod(): void; + x: any; + method(): void; +}`, +}, + +);