From eba4d3673931dc748cdf5b0e4633646b23a0deb9 Mon Sep 17 00:00:00 2001 From: kingwl <805037171@163.com> Date: Thu, 14 Dec 2017 09:26:05 +0800 Subject: [PATCH 01/62] error if import empty object form module not existed --- src/compiler/checker.ts | 5 ++++- .../reference/importEmptyFromModuleNotExisted.errors.txt | 8 ++++++++ .../reference/importEmptyFromModuleNotExisted.js | 7 +++++++ .../reference/importEmptyFromModuleNotExisted.symbols | 4 ++++ .../reference/importEmptyFromModuleNotExisted.types | 4 ++++ .../es6/modules/importEmptyFromModuleNotExisted.ts | 1 + 6 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/importEmptyFromModuleNotExisted.errors.txt create mode 100644 tests/baselines/reference/importEmptyFromModuleNotExisted.js create mode 100644 tests/baselines/reference/importEmptyFromModuleNotExisted.symbols create mode 100644 tests/baselines/reference/importEmptyFromModuleNotExisted.types create mode 100644 tests/cases/conformance/es6/modules/importEmptyFromModuleNotExisted.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bb7f8d013fc..0c44bd928a7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23852,7 +23852,10 @@ namespace ts { checkImportBinding(importClause.namedBindings); } else { - forEach(importClause.namedBindings.elements, checkImportBinding); + const moduleExisted = resolveExternalModuleName(node, node.moduleSpecifier); + if (moduleExisted) { + forEach(importClause.namedBindings.elements, checkImportBinding); + } } } } diff --git a/tests/baselines/reference/importEmptyFromModuleNotExisted.errors.txt b/tests/baselines/reference/importEmptyFromModuleNotExisted.errors.txt new file mode 100644 index 00000000000..99ccd49c489 --- /dev/null +++ b/tests/baselines/reference/importEmptyFromModuleNotExisted.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/es6/modules/importEmptyFromModuleNotExisted.ts(1,16): error TS2307: Cannot find module 'module-not-existed'. + + +==== tests/cases/conformance/es6/modules/importEmptyFromModuleNotExisted.ts (1 errors) ==== + import {} from 'module-not-existed' + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'module-not-existed'. + \ No newline at end of file diff --git a/tests/baselines/reference/importEmptyFromModuleNotExisted.js b/tests/baselines/reference/importEmptyFromModuleNotExisted.js new file mode 100644 index 00000000000..aa08db2e99e --- /dev/null +++ b/tests/baselines/reference/importEmptyFromModuleNotExisted.js @@ -0,0 +1,7 @@ +//// [importEmptyFromModuleNotExisted.ts] +import {} from 'module-not-existed' + + +//// [importEmptyFromModuleNotExisted.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/importEmptyFromModuleNotExisted.symbols b/tests/baselines/reference/importEmptyFromModuleNotExisted.symbols new file mode 100644 index 00000000000..ea0425ff26c --- /dev/null +++ b/tests/baselines/reference/importEmptyFromModuleNotExisted.symbols @@ -0,0 +1,4 @@ +=== tests/cases/conformance/es6/modules/importEmptyFromModuleNotExisted.ts === +import {} from 'module-not-existed' +No type information for this code. +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/importEmptyFromModuleNotExisted.types b/tests/baselines/reference/importEmptyFromModuleNotExisted.types new file mode 100644 index 00000000000..ea0425ff26c --- /dev/null +++ b/tests/baselines/reference/importEmptyFromModuleNotExisted.types @@ -0,0 +1,4 @@ +=== tests/cases/conformance/es6/modules/importEmptyFromModuleNotExisted.ts === +import {} from 'module-not-existed' +No type information for this code. +No type information for this code. \ No newline at end of file diff --git a/tests/cases/conformance/es6/modules/importEmptyFromModuleNotExisted.ts b/tests/cases/conformance/es6/modules/importEmptyFromModuleNotExisted.ts new file mode 100644 index 00000000000..36bca3e9619 --- /dev/null +++ b/tests/cases/conformance/es6/modules/importEmptyFromModuleNotExisted.ts @@ -0,0 +1 @@ +import {} from 'module-not-existed' From 4c4f0e8e65f5aebc28957e2ebc6921ba99e1feea Mon Sep 17 00:00:00 2001 From: falsandtru Date: Wed, 21 Mar 2018 17:18:42 +0900 Subject: [PATCH 02/62] Fix Promise interfaces --- src/lib/es2015.promise.d.ts | 2 +- src/lib/es5.d.ts | 4 +++- .../reference/defaultExportInAwaitExpression01.types | 6 +++--- .../reference/defaultExportInAwaitExpression02.types | 6 +++--- tests/baselines/reference/inferenceLimit.types | 12 ++++++------ ...dularizeLibrary_NoErrorDuplicateLibOptions1.types | 4 ++-- ...dularizeLibrary_NoErrorDuplicateLibOptions2.types | 4 ++-- .../modularizeLibrary_TargetES5UsingES6Lib.types | 4 ++-- tests/baselines/reference/usePromiseFinally.types | 4 ++-- 9 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/lib/es2015.promise.d.ts b/src/lib/es2015.promise.d.ts index ab33531191f..af43abe63d6 100644 --- a/src/lib/es2015.promise.d.ts +++ b/src/lib/es2015.promise.d.ts @@ -10,7 +10,7 @@ interface PromiseConstructor { * a resolve callback used resolve the promise with a value or the result of another promise, * and a reject callback used to reject the promise with a provided reason or error. */ - new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + new (executor: (resolve: [T] extends [void] ? (value?: T | PromiseLike) => void : (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; /** * Creates a Promise that is resolved with an array of results when all of the provided Promises diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 1f352cd6f39..c213677feac 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1273,7 +1273,9 @@ declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) declare type MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void; declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void; -declare type PromiseConstructorLike = new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void) => PromiseLike; +interface PromiseConstructorLike { + new (executor: (resolve: [T] extends [void] ? (value?: T | PromiseLike) => void : (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): PromiseLike; +} interface PromiseLike { /** diff --git a/tests/baselines/reference/defaultExportInAwaitExpression01.types b/tests/baselines/reference/defaultExportInAwaitExpression01.types index 1f7de76b90e..a68e9b88fa2 100644 --- a/tests/baselines/reference/defaultExportInAwaitExpression01.types +++ b/tests/baselines/reference/defaultExportInAwaitExpression01.types @@ -3,11 +3,11 @@ const x = new Promise( ( resolve, reject ) => { resolve( {} ); } ); >x : Promise<{}> >new Promise( ( resolve, reject ) => { resolve( {} ); } ) : Promise<{}> >Promise : PromiseConstructor ->( resolve, reject ) => { resolve( {} ); } : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value?: {} | PromiseLike<{}>) => void +>( resolve, reject ) => { resolve( {} ); } : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void >resolve( {} ) : void ->resolve : (value?: {} | PromiseLike<{}>) => void +>resolve : (value: {} | PromiseLike<{}>) => void >{} : {} export default x; diff --git a/tests/baselines/reference/defaultExportInAwaitExpression02.types b/tests/baselines/reference/defaultExportInAwaitExpression02.types index 1f7de76b90e..a68e9b88fa2 100644 --- a/tests/baselines/reference/defaultExportInAwaitExpression02.types +++ b/tests/baselines/reference/defaultExportInAwaitExpression02.types @@ -3,11 +3,11 @@ const x = new Promise( ( resolve, reject ) => { resolve( {} ); } ); >x : Promise<{}> >new Promise( ( resolve, reject ) => { resolve( {} ); } ) : Promise<{}> >Promise : PromiseConstructor ->( resolve, reject ) => { resolve( {} ); } : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value?: {} | PromiseLike<{}>) => void +>( resolve, reject ) => { resolve( {} ); } : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void >resolve( {} ) : void ->resolve : (value?: {} | PromiseLike<{}>) => void +>resolve : (value: {} | PromiseLike<{}>) => void >{} : {} export default x; diff --git a/tests/baselines/reference/inferenceLimit.types b/tests/baselines/reference/inferenceLimit.types index 4a398932232..16e030241c2 100644 --- a/tests/baselines/reference/inferenceLimit.types +++ b/tests/baselines/reference/inferenceLimit.types @@ -21,8 +21,8 @@ export class BrokenClass { >Array : T[] >MyModule : any >MyModel : MyModule.MyModel ->(resolve, reject) => { let result: Array = []; let populateItems = (order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); }; return Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }); } : (resolve: (value?: MyModule.MyModel[] | PromiseLike) => void, reject: (reason?: any) => void) => Promise ->resolve : (value?: MyModule.MyModel[] | PromiseLike) => void +>(resolve, reject) => { let result: Array = []; let populateItems = (order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); }; return Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }); } : (resolve: (value: MyModule.MyModel[] | PromiseLike) => void, reject: (reason?: any) => void) => Promise +>resolve : (value: MyModule.MyModel[] | PromiseLike) => void >reject : (reason?: any) => void let result: Array = []; @@ -40,8 +40,8 @@ export class BrokenClass { return new Promise((resolve, reject) => { >new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }) : Promise<{}> >Promise : PromiseConstructor ->(resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); } : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value?: {} | PromiseLike<{}>) => void +>(resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); } : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void this.doStuff(order.id) @@ -69,7 +69,7 @@ export class BrokenClass { resolve(order); >resolve(order) : void ->resolve : (value?: {} | PromiseLike<{}>) => void +>resolve : (value: {} | PromiseLike<{}>) => void >order : any }); @@ -99,7 +99,7 @@ export class BrokenClass { resolve(orders); >resolve(orders) : void ->resolve : (value?: MyModule.MyModel[] | PromiseLike) => void +>resolve : (value: MyModule.MyModel[] | PromiseLike) => void >orders : MyModule.MyModel[] }); diff --git a/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types b/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types index 78e6a6bc3f5..bda310b20e4 100644 --- a/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types +++ b/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types @@ -138,8 +138,8 @@ async function out() { return new Promise(function (resolve, reject) {}); >new Promise(function (resolve, reject) {}) : Promise<{}> >Promise : PromiseConstructor ->function (resolve, reject) {} : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value?: {} | PromiseLike<{}>) => void +>function (resolve, reject) {} : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void } diff --git a/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types b/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types index 4aabae824ee..8d05cc40ce4 100644 --- a/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types +++ b/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types @@ -138,8 +138,8 @@ async function out() { return new Promise(function (resolve, reject) {}); >new Promise(function (resolve, reject) {}) : Promise<{}> >Promise : PromiseConstructor ->function (resolve, reject) {} : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value?: {} | PromiseLike<{}>) => void +>function (resolve, reject) {} : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void } diff --git a/tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types b/tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types index 2782c70ebd9..9334b118d71 100644 --- a/tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types +++ b/tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types @@ -138,8 +138,8 @@ async function out() { return new Promise(function (resolve, reject) {}); >new Promise(function (resolve, reject) {}) : Promise<{}> >Promise : PromiseConstructor ->function (resolve, reject) {} : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value?: {} | PromiseLike<{}>) => void +>function (resolve, reject) {} : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void } diff --git a/tests/baselines/reference/usePromiseFinally.types b/tests/baselines/reference/usePromiseFinally.types index 80534c75610..2dd2d82da79 100644 --- a/tests/baselines/reference/usePromiseFinally.types +++ b/tests/baselines/reference/usePromiseFinally.types @@ -5,8 +5,8 @@ let promise1 = new Promise(function(resolve, reject) {}) >new Promise(function(resolve, reject) {}) .finally : (onfinally?: () => void) => Promise<{}> >new Promise(function(resolve, reject) {}) : Promise<{}> >Promise : PromiseConstructor ->function(resolve, reject) {} : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value?: {} | PromiseLike<{}>) => void +>function(resolve, reject) {} : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void .finally(function() {}); From b0fb73c47cc7202f2477a4140dd3e2303d6aefce Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 3 Apr 2018 13:53:19 -0700 Subject: [PATCH 03/62] Typings cache is internal data structure --- src/server/editorServices.ts | 3 ++- src/server/typingsCache.ts | 3 ++- tests/baselines/reference/api/tsserverlibrary.d.ts | 12 ------------ 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 1f8f9d3b21b..dc2fa086a93 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -312,7 +312,8 @@ namespace ts.server { export class ProjectService { - public readonly typingsCache: TypingsCache; + /*@internal*/ + readonly typingsCache: TypingsCache; private readonly documentRegistry: DocumentRegistry; diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index f2642230f2d..6418b5f9cbe 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -24,7 +24,7 @@ namespace ts.server { globalTypingsCacheLocation: undefined }; - class TypingsCacheEntry { + interface TypingsCacheEntry { readonly typeAcquisition: TypeAcquisition; readonly compilerOptions: CompilerOptions; readonly typings: SortedReadonlyArray; @@ -80,6 +80,7 @@ namespace ts.server { return !arrayIsEqualTo(imports1, imports2); } + /*@internal*/ export class TypingsCache { private readonly perProjectCache: Map = createMap(); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2e8e3f3871d..d102f467ade 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7602,17 +7602,6 @@ declare namespace ts.server { readonly globalTypingsCacheLocation: string; } const nullTypingsInstaller: ITypingsInstaller; - class TypingsCache { - private readonly installer; - private readonly perProjectCache; - constructor(installer: ITypingsInstaller); - isKnownTypesPackageName(name: string): boolean; - installPackage(options: InstallPackageOptionsWithProject): Promise; - getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean): SortedReadonlyArray; - updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, newTypings: string[]): void; - deleteTypingsForProject(projectName: string): void; - onProjectClosed(project: Project): void; - } } declare namespace ts.server { enum ProjectKind { @@ -7960,7 +7949,6 @@ declare namespace ts.server { syntaxOnly?: boolean; } class ProjectService { - readonly typingsCache: TypingsCache; private readonly documentRegistry; /** * Container of all known scripts From c9479f7263fbd51f454da2b6363238200e0abca8 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Apr 2018 14:55:22 -0700 Subject: [PATCH 04/62] Remove the specialized type UnresolvedImportsMap which is just a redirection and helps only in test only --- src/harness/unittests/typingsInstaller.ts | 6 +-- src/server/project.ts | 42 +++---------------- .../reference/api/tsserverlibrary.d.ts | 12 ------ 3 files changed, 9 insertions(+), 51 deletions(-) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 1a19c98f477..5ec7a9d7a17 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -999,7 +999,7 @@ namespace ts.projectSystem { proj.updateGraph(); assert.deepEqual( - proj.getCachedUnresolvedImportsPerFile_TestOnly().get(f1.path), + proj.cachedUnresolvedImportsPerFile.get(f1.path), ["foo", "foo", "foo", "@bar/router", "@bar/common", "@bar/common"] ); @@ -1029,7 +1029,7 @@ namespace ts.projectSystem { const projectService = session.getProjectService(); checkNumberOfProjects(projectService, { inferredProjects: 1 }); const proj = projectService.inferredProjects[0]; - const version1 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion(); + const version1 = proj.lastCachedUnresolvedImportsList; // make a change that should not affect the structure of the program const changeRequest: server.protocol.ChangeRequest = { @@ -1047,7 +1047,7 @@ namespace ts.projectSystem { }; session.executeCommand(changeRequest); host.checkTimeoutQueueLengthAndRun(2); // This enqueues the updategraph and refresh inferred projects - const version2 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion(); + const version2 = proj.lastCachedUnresolvedImportsList; assert.notEqual(version1, version2, "set of unresolved imports should change"); }); diff --git a/src/server/project.ts b/src/server/project.ts index 1502d107dee..23583d9c71b 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -55,34 +55,6 @@ namespace ts.server { projectErrors: ReadonlyArray; } - export class UnresolvedImportsMap { - readonly perFileMap = createMap>(); - private version = 0; - - public clear() { - this.perFileMap.clear(); - this.version = 0; - } - - public getVersion() { - return this.version; - } - - public remove(path: Path) { - this.perFileMap.delete(path); - this.version++; - } - - public get(path: Path) { - return this.perFileMap.get(path); - } - - public set(path: Path, value: ReadonlyArray) { - this.perFileMap.set(path, value); - this.version++; - } - } - export interface PluginCreateInfo { project: Project; languageService: LanguageService; @@ -116,8 +88,10 @@ namespace ts.server { private missingFilesMap: Map; private plugins: PluginModule[] = []; - private cachedUnresolvedImportsPerFile = new UnresolvedImportsMap(); - private lastCachedUnresolvedImportsList: SortedReadonlyArray; + /*@internal*/ + cachedUnresolvedImportsPerFile = createMap>(); + /*@internal*/ + lastCachedUnresolvedImportsList: SortedReadonlyArray; private lastFileExceededProgramSize: string | undefined; @@ -181,10 +155,6 @@ namespace ts.server { return hasOneOrMoreJsAndNoTsFiles(this); } - public getCachedUnresolvedImportsPerFile_TestOnly() { - return this.cachedUnresolvedImportsPerFile; - } - public static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} { const resolvedPath = normalizeSlashes(host.resolvePath(combinePaths(initialDir, "node_modules"))); log(`Loading ${moduleName} from ${initialDir} (resolved to ${resolvedPath})`); @@ -742,7 +712,7 @@ namespace ts.server { else { this.resolutionCache.invalidateResolutionOfFile(info.path); } - this.cachedUnresolvedImportsPerFile.remove(info.path); + this.cachedUnresolvedImportsPerFile.delete(info.path); if (detachFromProject) { info.detachFromProject(this); @@ -812,7 +782,7 @@ namespace ts.server { for (const file of changedFiles) { // delete cached information for changed files - this.cachedUnresolvedImportsPerFile.remove(file); + this.cachedUnresolvedImportsPerFile.delete(file); } // update builder only if language service is enabled diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index d102f467ade..29959a89d02 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7611,15 +7611,6 @@ declare namespace ts.server { } function allRootFilesAreJsOrDts(project: Project): boolean; function allFilesAreJsOrDts(project: Project): boolean; - class UnresolvedImportsMap { - readonly perFileMap: Map>; - private version; - clear(): void; - getVersion(): number; - remove(path: Path): void; - get(path: Path): ReadonlyArray; - set(path: Path, value: ReadonlyArray): void; - } interface PluginCreateInfo { project: Project; languageService: LanguageService; @@ -7652,8 +7643,6 @@ declare namespace ts.server { private externalFiles; private missingFilesMap; private plugins; - private cachedUnresolvedImportsPerFile; - private lastCachedUnresolvedImportsList; private lastFileExceededProgramSize; protected languageService: LanguageService; languageServiceEnabled: boolean; @@ -7688,7 +7677,6 @@ declare namespace ts.server { private readonly cancellationToken; isNonTsProject(): boolean; isJsOnlyProject(): boolean; - getCachedUnresolvedImportsPerFile_TestOnly(): UnresolvedImportsMap; static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {}; isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptions): Promise; From 35abe268242207c58558d3e7d6077ffe09e2f779 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Apr 2018 15:21:20 -0700 Subject: [PATCH 05/62] Force new typings resolution only if there are more or less script infos in the project. This helps in reducing number of forced typing installation requests We anyways use changes in unresolved import array to determine if we need to enqueue new typing request Hence there is no need to soley rely on hasChanges from updateGraph which just indicates that we didnt reused the program (that does not mean new files were added to the program or changes in unresolved imports) --- src/compiler/core.ts | 7 ++++--- src/server/project.ts | 6 +++++- src/server/scriptInfo.ts | 8 +++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index cdf68cb2dfa..b427c689c96 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2987,18 +2987,19 @@ namespace ts { } /** Remove the *first* occurrence of `item` from the array. */ - export function unorderedRemoveItem(array: T[], item: T): void { + export function unorderedRemoveItem(array: T[], item: T) { unorderedRemoveFirstItemWhere(array, element => element === item); } /** Remove the *first* element satisfying `predicate`. */ - function unorderedRemoveFirstItemWhere(array: T[], predicate: (element: T) => boolean): void { + function unorderedRemoveFirstItemWhere(array: T[], predicate: (element: T) => boolean) { for (let i = 0; i < array.length; i++) { if (predicate(array[i])) { unorderedRemoveItemAt(array, i); - break; + return true; } } + return false; } export type GetCanonicalFileName = (fileName: string) => string; diff --git a/src/server/project.ts b/src/server/project.ts index 23583d9c71b..47bfb03a189 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -92,6 +92,8 @@ namespace ts.server { cachedUnresolvedImportsPerFile = createMap>(); /*@internal*/ lastCachedUnresolvedImportsList: SortedReadonlyArray; + /*@internal*/ + hasMoreOrLessScriptInfos = false; private lastFileExceededProgramSize: string | undefined; @@ -777,6 +779,8 @@ namespace ts.server { this.resolutionCache.startRecordingFilesWithChangedResolutions(); let hasChanges = this.updateGraphWorker(); + const hasMoreOrLessScriptInfos = this.hasMoreOrLessScriptInfos; + this.hasMoreOrLessScriptInfos = false; const changedFiles: ReadonlyArray = this.resolutionCache.finishRecordingFilesWithChangedResolutions() || emptyArray; @@ -803,7 +807,7 @@ namespace ts.server { this.lastCachedUnresolvedImportsList = toDeduplicatedSortedArray(result); } - const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasChanges); + const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasMoreOrLessScriptInfos); if (!arrayIsEqualTo(this.typingFiles, cachedTypings)) { this.typingFiles = cachedTypings; this.markAsDirty(); diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index db56973d796..074fde298aa 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -304,6 +304,7 @@ namespace ts.server { const isNew = !this.isAttached(project); if (isNew) { this.containingProjects.push(project); + project.hasMoreOrLessScriptInfos = true; if (!project.getCompilerOptions().preserveSymlinks) { this.ensureRealPath(); } @@ -328,19 +329,24 @@ namespace ts.server { return; case 1: if (this.containingProjects[0] === project) { + project.hasMoreOrLessScriptInfos = true; this.containingProjects.pop(); } break; case 2: if (this.containingProjects[0] === project) { + project.hasMoreOrLessScriptInfos = true; this.containingProjects[0] = this.containingProjects.pop(); } else if (this.containingProjects[1] === project) { + project.hasMoreOrLessScriptInfos = true; this.containingProjects.pop(); } break; default: - unorderedRemoveItem(this.containingProjects, project); + if (unorderedRemoveItem(this.containingProjects, project)) { + project.hasMoreOrLessScriptInfos = true; + } break; } } From 60b19f5782b87af71a2ca567da9c3f9d50638df2 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Apr 2018 16:47:40 -0700 Subject: [PATCH 06/62] Invalidate the unresolved import resolutions when typing files are set This has 3 changes: 1. In updateGraph when enqueue the typing installation request (depending on unresolved imports) 2. When ActionSet event is received, invalidate only files with unresolved imports and resolve those. 3. When ActionInvalidate event is received, typing installer has detected some change in global typing cache location, so just enqueue a new typing installation request. This will repeat the cycle of setting correct typings and pickiing unresolved imports --- src/compiler/resolutionCache.ts | 20 ++++- .../unittests/tsserverProjectSystem.ts | 1 - src/harness/unittests/typingsInstaller.ts | 75 ++++++++++++++++++- src/server/editorServices.ts | 10 +-- src/server/project.ts | 71 ++++++++++++------ src/server/typingsCache.ts | 16 ++-- .../reference/api/tsserverlibrary.d.ts | 5 +- 7 files changed, 153 insertions(+), 45 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index c2b96649cf2..2cd39068de1 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -10,6 +10,7 @@ namespace ts { invalidateResolutionOfFile(filePath: Path): void; removeResolutionsOfFile(filePath: Path): void; + setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map): void; createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution; startCachingPerDirectoryResolution(): void; @@ -74,6 +75,7 @@ namespace ts { export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string, logChangesWhenResolvingModule: boolean): ResolutionCache { let filesWithChangedSetOfUnresolvedImports: Path[] | undefined; let filesWithInvalidatedResolutions: Map | undefined; + let filesWithInvalidatedNonRelativeUnresolvedImports: Map | undefined; let allFilesHaveInvalidatedResolution = false; const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory()); @@ -122,6 +124,7 @@ namespace ts { resolveTypeReferenceDirectives, removeResolutionsOfFile, invalidateResolutionOfFile, + setFilesWithInvalidatedNonRelativeUnresolvedImports, createHasInvalidatedResolution, updateTypeRootsWatch, closeTypeRootsWatch, @@ -173,7 +176,8 @@ namespace ts { } const collected = filesWithInvalidatedResolutions; filesWithInvalidatedResolutions = undefined; - return path => collected && collected.has(path); + return path => (collected && collected.has(path)) || + (filesWithInvalidatedNonRelativeUnresolvedImports && filesWithInvalidatedNonRelativeUnresolvedImports.has(path)); } function clearPerDirectoryResolutions() { @@ -184,6 +188,7 @@ namespace ts { function finishCachingPerDirectoryResolution() { allFilesHaveInvalidatedResolution = false; + filesWithInvalidatedNonRelativeUnresolvedImports = undefined; directoryWatchesOfFailedLookups.forEach((watcher, path) => { if (watcher.refCount === 0) { directoryWatchesOfFailedLookups.delete(path); @@ -237,13 +242,15 @@ namespace ts { const resolvedModules: R[] = []; const compilerOptions = resolutionHost.getCompilationSettings(); - + const hasInvalidatedNonRelativeUnresolvedImport = logChanges && filesWithInvalidatedNonRelativeUnresolvedImports && filesWithInvalidatedNonRelativeUnresolvedImports.has(path); const seenNamesInFile = createMap(); for (const name of names) { let resolution = resolutionsInFile.get(name); // Resolution is valid if it is present and not invalidated if (!seenNamesInFile.has(name) && - allFilesHaveInvalidatedResolution || !resolution || resolution.isInvalidated) { + allFilesHaveInvalidatedResolution || !resolution || resolution.isInvalidated || + // If the name is unresolved import that was invalidated, recalculate + (hasInvalidatedNonRelativeUnresolvedImport && !isExternalModuleNameRelative(name) && !getResolutionWithResolvedFileName(resolution))) { const existingResolution = resolution; const resolutionInDirectory = perDirectoryResolution.get(name); if (resolutionInDirectory) { @@ -284,7 +291,7 @@ namespace ts { if (oldResolution === newResolution) { return true; } - if (!oldResolution || !newResolution || oldResolution.isInvalidated) { + if (!oldResolution || !newResolution) { return false; } const oldResult = getResolutionWithResolvedFileName(oldResolution); @@ -577,6 +584,11 @@ namespace ts { ); } + function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: Map) { + Debug.assert(filesWithInvalidatedNonRelativeUnresolvedImports === filesMap || filesWithInvalidatedNonRelativeUnresolvedImports === undefined); + filesWithInvalidatedNonRelativeUnresolvedImports = filesMap; + } + function invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath: Path, isCreatingWatchedDirectory: boolean) { let isChangedFailedLookupLocation: (location: string) => boolean; if (isCreatingWatchedDirectory) { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index b167ed21b94..10912b4fb87 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -7294,7 +7294,6 @@ namespace ts.projectSystem { const host = createServerHost(files); const session = createSession(host); const projectService = session.getProjectService(); - debugger; session.executeCommandSeq({ command: protocol.CommandTypes.Open, arguments: { diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 5ec7a9d7a17..b6d5a20ef9a 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1006,7 +1006,7 @@ namespace ts.projectSystem { installer.installAll(/*expectedCount*/ 1); }); - it("should recompute resolutions after typings are installed", () => { + it("cached unresolved typings are not recomputed if program structure did not change", () => { const host = createServerHost([]); const session = createSession(host); const f = { @@ -1048,7 +1048,7 @@ namespace ts.projectSystem { session.executeCommand(changeRequest); host.checkTimeoutQueueLengthAndRun(2); // This enqueues the updategraph and refresh inferred projects const version2 = proj.lastCachedUnresolvedImportsList; - assert.notEqual(version1, version2, "set of unresolved imports should change"); + assert.strictEqual(version1, version2, "set of unresolved imports should change"); }); it("expired cache entry (inferred project, should install typings)", () => { @@ -1621,4 +1621,75 @@ namespace ts.projectSystem { assert.deepEqual(commands, expectedCommands, "commands"); }); }); + + describe("recomputing resolutions of unresolved imports", () => { + const globalTypingsCacheLocation = "/tmp"; + const appPath = "/a/b/app.js" as Path; + const foooPath = "/a/b/node_modules/fooo/index.d.ts"; + function verifyResolvedModuleOfFooo(project: server.Project) { + const foooResolution = project.getLanguageService().getProgram().getSourceFileByPath(appPath).resolvedModules.get("fooo"); + assert.equal(foooResolution.resolvedFileName, foooPath); + return foooResolution; + } + + function verifyUnresolvedImportResolutions(appContents: string, typingNames: string[], typingFiles: FileOrFolder[]) { + const app: FileOrFolder = { + path: appPath, + content: `${appContents}import * as x from "fooo";` + }; + const fooo: FileOrFolder = { + path: foooPath, + content: `export var x: string;` + }; + const host = createServerHost([app, fooo]); + const installer = new (class extends Installer { + constructor() { + super(host, { globalTypingsCacheLocation, typesRegistry: createTypesRegistry("foo") }); + } + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { + executeCommand(this, host, typingNames, typingFiles, cb); + } + })(); + const projectService = createProjectService(host, { typingsInstaller: installer }); + projectService.openClientFile(app.path); + projectService.checkNumberOfProjects({ inferredProjects: 1 }); + + const proj = projectService.inferredProjects[0]; + checkProjectActualFiles(proj, [app.path, fooo.path]); + const foooResolution1 = verifyResolvedModuleOfFooo(proj); + + installer.installAll(/*expectedCount*/ 1); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(proj, typingFiles.map(f => f.path).concat(app.path, fooo.path)); + const foooResolution2 = verifyResolvedModuleOfFooo(proj); + assert.strictEqual(foooResolution1, foooResolution2); + } + + it("correctly invalidate the resolutions with typing names", () => { + verifyUnresolvedImportResolutions('import * as a from "foo";', ["foo"], [{ + path: `${globalTypingsCacheLocation}/node_modules/foo/index.d.ts`, + content: "export function a(): void;" + }]); + }); + + it("correctly invalidate the resolutions with typing names that are trimmed", () => { + const fooAA: FileOrFolder = { + path: `${globalTypingsCacheLocation}/node_modules/foo/a/a.d.ts`, + content: "export function a (): void;" + }; + const fooAB: FileOrFolder = { + path: `${globalTypingsCacheLocation}/node_modules/foo/a/b.d.ts`, + content: "export function b (): void;" + }; + const fooAC: FileOrFolder = { + path: `${globalTypingsCacheLocation}/node_modules/foo/a/c.d.ts`, + content: "export function c (): void;" + }; + verifyUnresolvedImportResolutions(` + import * as a from "foo/a/a"; + import * as b from "foo/a/b"; + import * as c from "foo/a/c"; + `, ["foo"], [fooAA, fooAB, fooAC]); + }); + }); } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index dc2fa086a93..1271b98c1c7 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -524,13 +524,13 @@ namespace ts.server { } switch (response.kind) { case ActionSet: - project.resolutionCache.clear(); - this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typeAcquisition, response.unresolvedImports, response.typings); + // Update the typing files and update the project + project.updateTypingFiles(this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typeAcquisition, response.unresolvedImports, response.typings)); break; case ActionInvalidate: - project.resolutionCache.clear(); - this.typingsCache.deleteTypingsForProject(response.projectName); - break; + // Do not clear resolution cache, there was changes detected in typings, so enque typing request and let it get us correct results + this.typingsCache.enqueueInstallTypingsForProject(project, project.lastCachedUnresolvedImportsList, /*forceRefresh*/ true); + return; } this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); } diff --git a/src/server/project.ts b/src/server/project.ts index 47bfb03a189..67469cc69d8 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -89,7 +89,18 @@ namespace ts.server { private plugins: PluginModule[] = []; /*@internal*/ + /** + * This is map from files to unresolved imports in it + * Maop does not contain entries for files that do not have unresolved imports + * This helps in containing the set of files to invalidate + */ cachedUnresolvedImportsPerFile = createMap>(); + + /** + * This is the set that has entry to true if file doesnt contain any unresolved import + */ + private filesWithNoUnresolvedImports = createMap(); + /*@internal*/ lastCachedUnresolvedImportsList: SortedReadonlyArray; /*@internal*/ @@ -143,7 +154,8 @@ namespace ts.server { /*@internal*/ hasChangedAutomaticTypeDirectiveNames = false; - private typingFiles: SortedReadonlyArray; + /*@internal*/ + typingFiles: SortedReadonlyArray = emptyArray; private readonly cancellationToken: ThrottledCancellationToken; @@ -554,6 +566,7 @@ namespace ts.server { this.resolutionCache.clear(); this.resolutionCache = undefined; this.cachedUnresolvedImportsPerFile = undefined; + this.filesWithNoUnresolvedImports = undefined; this.directoryStructureHost = undefined; // Clean up file watchers waiting for missing files @@ -714,6 +727,7 @@ namespace ts.server { else { this.resolutionCache.invalidateResolutionOfFile(info.path); } + this.filesWithNoUnresolvedImports.delete(info.path); this.cachedUnresolvedImportsPerFile.delete(info.path); if (detachFromProject) { @@ -735,16 +749,21 @@ namespace ts.server { } /* @internal */ - private extractUnresolvedImportsFromSourceFile(file: SourceFile, result: Push, ambientModules: string[]) { + private extractUnresolvedImportsFromSourceFile(file: SourceFile, result: string[] | undefined, ambientModules: string[]): string[] | undefined { + // No unresolve imports in this file + if (this.filesWithNoUnresolvedImports.has(file.path)) { + return result; + } + const cached = this.cachedUnresolvedImportsPerFile.get(file.path); if (cached) { // found cached result - use it and return for (const f of cached) { - result.push(f); + (result || (result = [])).push(f); } - return; + return result; } - let unresolvedImports: string[]; + let unresolvedImports: string[] | undefined; if (file.resolvedModules) { file.resolvedModules.forEach((resolvedModule, name) => { // pick unresolved non-relative names @@ -760,11 +779,17 @@ namespace ts.server { trimmed = trimmed.substr(0, i); } (unresolvedImports || (unresolvedImports = [])).push(trimmed); - result.push(trimmed); + (result || (result = [])).push(trimmed); } }); } - this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports || emptyArray); + if (unresolvedImports) { + this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports); + } + else { + this.filesWithNoUnresolvedImports.set(file.path, true); + } + return result; function isAmbientlyDeclaredModule(name: string) { return ambientModules.some(m => m === name); @@ -778,7 +803,7 @@ namespace ts.server { updateGraph(): boolean { this.resolutionCache.startRecordingFilesWithChangedResolutions(); - let hasChanges = this.updateGraphWorker(); + const hasChanges = this.updateGraphWorker(); const hasMoreOrLessScriptInfos = this.hasMoreOrLessScriptInfos; this.hasMoreOrLessScriptInfos = false; @@ -787,6 +812,7 @@ namespace ts.server { for (const file of changedFiles) { // delete cached information for changed files this.cachedUnresolvedImportsPerFile.delete(file); + this.filesWithNoUnresolvedImports.delete(file); } // update builder only if language service is enabled @@ -799,20 +825,15 @@ namespace ts.server { // (can reuse cached imports for files that were not changed) // 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch if (hasChanges || changedFiles.length) { - const result: string[] = []; + let result: string[] | undefined; const ambientModules = this.program.getTypeChecker().getAmbientModules().map(mod => stripQuotes(mod.getName())); for (const sourceFile of this.program.getSourceFiles()) { - this.extractUnresolvedImportsFromSourceFile(sourceFile, result, ambientModules); + result = this.extractUnresolvedImportsFromSourceFile(sourceFile, result, ambientModules); } - this.lastCachedUnresolvedImportsList = toDeduplicatedSortedArray(result); + this.lastCachedUnresolvedImportsList = result ? toDeduplicatedSortedArray(result) : emptyArray; } - const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasMoreOrLessScriptInfos); - if (!arrayIsEqualTo(this.typingFiles, cachedTypings)) { - this.typingFiles = cachedTypings; - this.markAsDirty(); - hasChanges = this.updateGraphWorker() || hasChanges; - } + this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasMoreOrLessScriptInfos); } else { this.lastCachedUnresolvedImportsList = undefined; @@ -824,6 +845,13 @@ namespace ts.server { return !hasChanges; } + /*@internal*/ + updateTypingFiles(typingFiles: SortedReadonlyArray) { + this.typingFiles = typingFiles; + // Invalidate files with unresolved imports + this.resolutionCache.setFilesWithInvalidatedNonRelativeUnresolvedImports(this.cachedUnresolvedImportsPerFile); + } + /* @internal */ getCurrentProgram() { return this.program; @@ -959,15 +987,14 @@ namespace ts.server { setCompilerOptions(compilerOptions: CompilerOptions) { if (compilerOptions) { compilerOptions.allowNonTsExtensions = true; - if (changesAffectModuleResolution(this.compilerOptions, compilerOptions)) { - // reset cached unresolved imports if changes in compiler options affected module resolution - this.cachedUnresolvedImportsPerFile.clear(); - this.lastCachedUnresolvedImportsList = undefined; - } const oldOptions = this.compilerOptions; this.compilerOptions = compilerOptions; this.setInternalCompilerOptionsForEmittingJsFiles(); if (changesAffectModuleResolution(oldOptions, compilerOptions)) { + // reset cached unresolved imports if changes in compiler options affected module resolution + this.cachedUnresolvedImportsPerFile.clear(); + this.filesWithNoUnresolvedImports.clear(); + this.lastCachedUnresolvedImportsList = undefined; this.resolutionCache.clear(); } this.markAsDirty(); diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index 6418b5f9cbe..c255757481f 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -95,15 +95,14 @@ namespace ts.server { return this.installer.installPackage(options); } - getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean): SortedReadonlyArray { + enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean) { const typeAcquisition = project.getTypeAcquisition(); if (!typeAcquisition || !typeAcquisition.enable) { - return emptyArray; + return; } const entry = this.perProjectCache.get(project.getProjectName()); - const result: SortedReadonlyArray = entry ? entry.typings : emptyArray; if (forceRefresh || !entry || typeAcquisitionChanged(typeAcquisition, entry.typeAcquisition) || @@ -114,28 +113,25 @@ namespace ts.server { this.perProjectCache.set(project.getProjectName(), { compilerOptions: project.getCompilationSettings(), typeAcquisition, - typings: result, + typings: entry ? entry.typings : emptyArray, unresolvedImports, poisoned: true }); // something has been changed, issue a request to update typings this.installer.enqueueInstallTypingsRequest(project, typeAcquisition, unresolvedImports); } - return result; } updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, newTypings: string[]) { + const typings = toSortedArray(newTypings); this.perProjectCache.set(projectName, { compilerOptions, typeAcquisition, - typings: toSortedArray(newTypings), + typings, unresolvedImports, poisoned: false }); - } - - deleteTypingsForProject(projectName: string) { - this.perProjectCache.delete(projectName); + return !typeAcquisition || !typeAcquisition.enable ? emptyArray : typings; } onProjectClosed(project: Project) { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 29959a89d02..53c23b1d382 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7643,6 +7643,10 @@ declare namespace ts.server { private externalFiles; private missingFilesMap; private plugins; + /** + * This is the set that has entry to true if file doesnt contain any unresolved import + */ + private filesWithNoUnresolvedImports; private lastFileExceededProgramSize; protected languageService: LanguageService; languageServiceEnabled: boolean; @@ -7673,7 +7677,6 @@ declare namespace ts.server { * This property is different from projectStructureVersion since in most cases edits don't affect set of files in the project */ private projectStateVersion; - private typingFiles; private readonly cancellationToken; isNonTsProject(): boolean; isJsOnlyProject(): boolean; From 82e9a7595b9c289875e15c706f608e913fce2fcb Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 13 Apr 2018 15:15:09 -0700 Subject: [PATCH 07/62] Invoked should be property on watchers map instead of local variable since watchers arent closed if they need to be reopened --- src/server/typingsInstaller/typingsInstaller.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 8d482241d1b..f79564f6f98 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -64,11 +64,13 @@ namespace ts.server.typingsInstaller { onRequestCompleted: RequestCompletedAction; } + type ProjectWatchers = Map & { isInvoked?: boolean; }; + export abstract class TypingsInstaller { private readonly packageNameToTypingLocation: Map = createMap(); private readonly missingTypingsSet: Map = createMap(); private readonly knownCachesSet: Map = createMap(); - private readonly projectWatchers = createMap>(); + private readonly projectWatchers = createMap(); private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; @@ -378,8 +380,8 @@ namespace ts.server.typingsInstaller { this.projectWatchers.set(projectName, watchers); } + watchers.isInvoked = false; // handler should be invoked once for the entire set of files since it will trigger full rediscovery of typings - let isInvoked = false; const isLoggingEnabled = this.log.isEnabled(); mutateMap( watchers, @@ -392,11 +394,11 @@ namespace ts.server.typingsInstaller { } const watcher = this.installTypingHost.watchFile(file, (f, eventKind) => { if (isLoggingEnabled) { - this.log.writeLine(`FileWatcher:: Triggered with ${f} eventKind: ${FileWatcherEventKind[eventKind]}:: WatchInfo: ${file}:: handler is already invoked '${isInvoked}'`); + this.log.writeLine(`FileWatcher:: Triggered with ${f} eventKind: ${FileWatcherEventKind[eventKind]}:: WatchInfo: ${file}:: handler is already invoked '${watchers.isInvoked}'`); } - if (!isInvoked) { + if (!watchers.isInvoked) { + watchers.isInvoked = true; this.sendResponse({ projectName, kind: ActionInvalidate }); - isInvoked = true; } }, /*pollingInterval*/ 2000); return isLoggingEnabled ? { From bd3e854b31781edfd03f087faf6de21b2bf1b783 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 20:51:09 -0700 Subject: [PATCH 08/62] Automatically configure tsc output and provide a new 'diagnosticStyle' option. --- src/compiler/commandLineParser.ts | 8 ++++++++ src/compiler/sys.ts | 4 ++++ src/compiler/tsc.ts | 11 +++++++++-- src/compiler/types.ts | 6 ++++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 470bd111492..252ea9e8df0 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -56,6 +56,14 @@ namespace ts { category: Diagnostics.Command_line_Options, description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental }, + { + name: "diagnosticStyle", + type: createMapFromTemplate({ + auto: DiagnosticStyle.Auto, + pretty: DiagnosticStyle.Pretty, + simple: DiagnosticStyle.Simple, + }), + }, { name: "preserveWatchOutput", type: "boolean", diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index c37315a2e56..2a4616732dd 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -428,6 +428,7 @@ namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; + writeOutputIsTty?(): boolean; readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; @@ -561,6 +562,9 @@ namespace ts { write(s: string): void { process.stdout.write(s); }, + writeOutputIsTty() { + return process.stdout.isTTY; + }, readFile, writeFile, watchFile: getWatchFile(), diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index f16ca98c93d..5012b73e98a 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -19,11 +19,18 @@ namespace ts { let reportDiagnostic = createDiagnosticReporter(sys); function updateReportDiagnostic(options: CompilerOptions) { - if (options.pretty) { + if (shouldBePretty(options)) { reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true); } } + function shouldBePretty(options: CompilerOptions) { + if ((typeof options.pretty === "undefined" && typeof options.diagnosticStyle === "undefined") || options.diagnosticStyle === DiagnosticStyle.Auto) { + return !!sys.writeOutputIsTty && sys.writeOutputIsTty(); + } + return options.diagnosticStyle === DiagnosticStyle.Pretty || options.pretty; + } + function padLeft(s: string, length: number) { while (s.length < length) { s = " " + s; @@ -159,7 +166,7 @@ namespace ts { } function createWatchStatusReporter(options: CompilerOptions) { - return ts.createWatchStatusReporter(sys, !!options.pretty); + return ts.createWatchStatusReporter(sys, shouldBePretty(options)); } function createWatchOfConfigFile(configParseResult: ParsedCommandLine, optionsToExtend: CompilerOptions) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 987d403e7cd..802c175b573 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4193,7 +4193,8 @@ namespace ts { preserveSymlinks?: boolean; /* @internal */ preserveWatchOutput?: boolean; project?: string; - /* @internal */ pretty?: DiagnosticStyle; + /* @internal */ pretty?: boolean; + /* @internal */ diagnosticStyle?: DiagnosticStyle; reactNamespace?: string; jsxFactory?: string; removeComments?: boolean; @@ -4293,8 +4294,9 @@ namespace ts { /* @internal */ export const enum DiagnosticStyle { - Simple, + Auto, Pretty, + Simple, } /** Either a parsed command line or a parsed tsconfig.json */ From 7fd1dda13cf520a48671f553ba36a4e3e4f55350 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 20:59:06 -0700 Subject: [PATCH 09/62] Accepted baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2e8e3f3871d..dfe2f613078 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2888,6 +2888,7 @@ declare namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; + writeOutputIsTty?(): boolean; readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 378949d5b5b..6963bd95f72 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2888,6 +2888,7 @@ declare namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; + writeOutputIsTty?(): boolean; readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; From b409888cbcce4b0c393d9fa7b255905b5a6efcad Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:01:24 -0700 Subject: [PATCH 10/62] Added tests. --- .../taggedTemplatesWithTypeArguments1.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts new file mode 100644 index 00000000000..90509938dbc --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts @@ -0,0 +1,44 @@ +// @target: esnext + +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; + +interface Stuff { + x: number; + y: string; + z: boolean; +} + +export const a = f ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare function g( + strs: TemplateStringsArray, + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; + +export const b = g ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare let obj: { + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { + returnedObjProp: { + lastOne: T + } + } +} + +export const c = obj["prop"] `${(input) => { ...input }}` +c.returnedProp.x; +c.returnedProp.y; +c.returnedProp.z; \ No newline at end of file From 23567ee05daa02b3acf1ad3e19431c8415701908 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:01:34 -0700 Subject: [PATCH 11/62] Accepted baselines. --- ...ggedTemplatesWithTypeArguments1.errors.txt | 82 ++++++++ .../taggedTemplatesWithTypeArguments1.js | 66 +++++++ .../taggedTemplatesWithTypeArguments1.symbols | 136 +++++++++++++ .../taggedTemplatesWithTypeArguments1.types | 181 ++++++++++++++++++ 4 files changed, 465 insertions(+) create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.js create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.types diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt new file mode 100644 index 00000000000..700c98d54fe --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt @@ -0,0 +1,82 @@ +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(9,18): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(9,20): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(22,20): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(22,50): error TS1005: ',' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,18): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,30): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,53): error TS1128: Declaration or statement expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(40,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(41,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(42,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. + + +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts (10 errors) ==== + declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; + + interface Stuff { + x: number; + y: string; + z: boolean; + } + + export const a = f ` + ~~~~~~~~~~ + ~~~~~ +!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. + hello + ~~~~~~~~~ + ${stuff => stuff.x} + ~~~~~~~~~~~~~~~~~~~~~~~ + brave + ~~~~~~~~~ + ${stuff => stuff.y} + ~~~~~~~~~~~~~~~~~~~~~~~ + world + ~~~~~~~~~ + ${stuff => stuff.z} + ~~~~~~~~~~~~~~~~~~~~~~~ + `; + ~ +!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. + + declare function g( + strs: TemplateStringsArray, + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; + + export const b = g ` + ~~~~~ +!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. + ~ +!!! error TS1005: ',' expected. + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} + `; + + declare let obj: { + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { + returnedObjProp: { + lastOne: T + } + } + } + + export const c = obj["prop"] `${(input) => { ...input }}` + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. + ~~~~~ +!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. + ~~~ +!!! error TS1128: Declaration or statement expected. + c.returnedProp.x; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. + c.returnedProp.y; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. + c.returnedProp.z; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js new file mode 100644 index 00000000000..629571b4db0 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js @@ -0,0 +1,66 @@ +//// [taggedTemplatesWithTypeArguments1.ts] +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; + +interface Stuff { + x: number; + y: string; + z: boolean; +} + +export const a = f ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare function g( + strs: TemplateStringsArray, + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; + +export const b = g ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare let obj: { + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { + returnedObjProp: { + lastOne: T + } + } +} + +export const c = obj["prop"] `${(input) => { ...input }}` +c.returnedProp.x; +c.returnedProp.y; +c.returnedProp.z; + +//// [taggedTemplatesWithTypeArguments1.js] +export const a = f < Stuff > ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; +export const b = g < Stuff, number, string, boolean; + > ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; +export const c = obj["prop"] < Stuff > `${(input) => { input; }}`; +c.returnedProp.x; +c.returnedProp.y; +c.returnedProp.z; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols new file mode 100644 index 00000000000..85170aad228 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols @@ -0,0 +1,136 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts === +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; +>f : Symbol(f, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 0)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 19)) +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 22)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>callbacks : Symbol(callbacks, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 49)) +>Array : Symbol(Array, Decl(lib.es2016.array.include.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --) ... and 1 more) +>x : Symbol(x, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 71)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 19)) + +interface Stuff { +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) + + x: number; +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) + + y: string; +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) + + z: boolean; +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) +} + +export const a = f ` +>a : Symbol(a, Decl(taggedTemplatesWithTypeArguments1.ts, 8, 12)) +>f : Symbol(f, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 0)) + + hello + ${stuff => stuff.x} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) + + brave + ${stuff => stuff.y} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) + + world + ${stuff => stuff.z} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) + +`; + +declare function g( +>g : Symbol(g, Decl(taggedTemplatesWithTypeArguments1.ts, 15, 2)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) + + strs: TemplateStringsArray, +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 35)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) + + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; +>t : Symbol(t, Decl(taggedTemplatesWithTypeArguments1.ts, 18, 31)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 8)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>u : Symbol(u, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 23)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 28)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>v : Symbol(v, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 43)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 48)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) + +export const b = g ` +>b : Symbol(b, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 12)) +>g : Symbol(g, Decl(taggedTemplatesWithTypeArguments1.ts, 15, 2)) +>number : Symbol(number, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 25)) +>string : Symbol(string, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 33)) +>boolean : Symbol(boolean, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 41)) + + hello + ${stuff => stuff.x} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) + + brave + ${stuff => stuff.y} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) + + world + ${stuff => stuff.z} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) + +`; + +declare let obj: { +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) + + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { +>prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 14)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 41)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 46)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) + + returnedObjProp: { +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) + + lastOne: T +>lastOne : Symbol(lastOne, Decl(taggedTemplatesWithTypeArguments1.ts, 32, 26)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) + } + } +} + +export const c = obj["prop"] `${(input) => { ...input }}` +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) +>"prop" : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 40)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 40)) + +c.returnedProp.x; +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) + +c.returnedProp.y; +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) + +c.returnedProp.z; +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) + diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types new file mode 100644 index 00000000000..9999bb67bd8 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types @@ -0,0 +1,181 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts === +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; +>f : (strs: TemplateStringsArray, ...callbacks: ((x: T) => any)[]) => void +>T : T +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>callbacks : ((x: T) => any)[] +>Array : T[] +>x : T +>T : T + +interface Stuff { +>Stuff : Stuff + + x: number; +>x : number + + y: string; +>y : string + + z: boolean; +>z : boolean +} + +export const a = f ` +>a : boolean +>f ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : boolean +>ff : (strs: TemplateStringsArray, ...callbacks: ((x: T) => any)[]) => void +>Stuff : any +>` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string + + hello + ${stuff => stuff.x} +>stuff => stuff.x : (stuff: any) => any +>stuff : any +>stuff.x : any +>stuff : any +>x : any + + brave + ${stuff => stuff.y} +>stuff => stuff.y : (stuff: any) => any +>stuff : any +>stuff.y : any +>stuff : any +>y : any + + world + ${stuff => stuff.z} +>stuff => stuff.z : (stuff: any) => any +>stuff : any +>stuff.z : any +>stuff : any +>z : any + +`; + +declare function g( +>g : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V +>Input : Input +>T : T +>U : U +>V : V + + strs: TemplateStringsArray, +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray + + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; +>t : (i: Input) => T +>i : Input +>Input : Input +>T : T +>u : (i: Input) => U +>i : Input +>Input : Input +>U : U +>v : (i: Input) => V +>i : Input +>Input : Input +>V : V +>T : T +>U : U +>V : V + +export const b = g ` +>b : boolean +>gg : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V +>Stuff : any +>number : any +>string : any +>boolean : any +>> ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : boolean +> : any +>` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string + + hello + ${stuff => stuff.x} +>stuff => stuff.x : (stuff: any) => any +>stuff : any +>stuff.x : any +>stuff : any +>x : any + + brave + ${stuff => stuff.y} +>stuff => stuff.y : (stuff: any) => any +>stuff : any +>stuff.y : any +>stuff : any +>y : any + + world + ${stuff => stuff.z} +>stuff => stuff.z : (stuff: any) => any +>stuff : any +>stuff.z : any +>stuff : any +>z : any + +`; + +declare let obj: { +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; }; } + + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { +>prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; } +>T : T +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>x : (input: T) => T +>input : T +>T : T +>T : T + + returnedObjProp: { +>returnedObjProp : { lastOne: T; } + + lastOne: T +>lastOne : T +>T : T + } + } +} + +export const c = obj["prop"] `${(input) => { ...input }}` +>c : boolean +>obj["prop"] `${(input) => { ...input }}` : boolean +>obj["prop"]obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; }; } +>"prop" : "prop" +>Stuff : any +>`${(input) => { ...input }}` : string +>(input) => { ...input } : (input: any) => void +>input : any +>input : any + +c.returnedProp.x; +>c.returnedProp.x : any +>c.returnedProp : any +>c : boolean +>returnedProp : any +>x : any + +c.returnedProp.y; +>c.returnedProp.y : any +>c.returnedProp : any +>c : boolean +>returnedProp : any +>y : any + +c.returnedProp.z; +>c.returnedProp.z : any +>c.returnedProp : any +>c : boolean +>returnedProp : any +>z : any + From 60b6d3fbce4f25d099995e2a62a9252f8546d5bf Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:14:13 -0700 Subject: [PATCH 12/62] Fixed up test. Thanks arrow functions... --- .../taggedTemplatesWithTypeArguments1.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts index 90509938dbc..2f3fc71e65d 100644 --- a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts @@ -32,13 +32,16 @@ export const b = g ` declare let obj: { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { - returnedObjProp: { - lastOne: T - } + returnedObjProp: T } } -export const c = obj["prop"] `${(input) => { ...input }}` -c.returnedProp.x; -c.returnedProp.y; -c.returnedProp.z; \ No newline at end of file +export let c = obj["prop"] `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; + +c = obj.prop `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; \ No newline at end of file From da7967a3cf535c131791e94f52bc0eb6d872fae3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:15:02 -0700 Subject: [PATCH 13/62] Added basic support for parsing/emitting type arguments in tagged template expressions. --- src/compiler/emitter.ts | 1 + src/compiler/parser.ts | 36 +++++++++++++++++++++++++++--------- src/compiler/types.ts | 1 + 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 289f332cd33..2b01f2fdda1 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1462,6 +1462,7 @@ namespace ts { function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { emitExpression(node.tag); + emitTypeArguments(node, node.typeArguments); writeSpace(); emitExpression(node.template); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 74d54ed28fb..29d57c846f5 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -223,6 +223,7 @@ namespace ts { visitNodes(cbNode, cbNodes, (node).arguments); case SyntaxKind.TaggedTemplateExpression: return visitNode(cbNode, (node).tag) || + visitNodes(cbNode, cbNodes, (node).typeArguments) || visitNode(cbNode, (node).template); case SyntaxKind.TypeAssertionExpression: return visitNode(cbNode, (node).type) || @@ -4362,18 +4363,28 @@ namespace ts { continue; } - if (token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead) { - const tagExpression = createNode(SyntaxKind.TaggedTemplateExpression, expression.pos); - tagExpression.tag = expression; - tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral - ? parseLiteralNode() - : parseTemplateExpression(); - expression = finishNode(tagExpression); + if (isTemplateStartOfTaggedTemplate()) { + expression = parseTaggedTemplateRest(expression, /*typeArguments*/ undefined); continue; } return expression; } + + } + + function isTemplateStartOfTaggedTemplate() { + return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead; + } + + function parseTaggedTemplateRest(tag: LeftHandSideExpression, typeArguments: NodeArray | undefined) { + const tagExpression = createNode(SyntaxKind.TaggedTemplateExpression, tag.pos); + tagExpression.tag = tag; + tagExpression.typeArguments = typeArguments; + tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral + ? parseLiteralNode() + : parseTemplateExpression(); + return finishNode(tagExpression); } function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression { @@ -4389,6 +4400,11 @@ namespace ts { return expression; } + if (isTemplateStartOfTaggedTemplate()) { + expression = parseTaggedTemplateRest(expression, typeArguments); + continue; + } + const callExpr = createNode(SyntaxKind.CallExpression, expression.pos); callExpr.expression = expression; callExpr.typeArguments = typeArguments; @@ -4436,8 +4452,10 @@ namespace ts { function canFollowTypeArgumentsInExpression(): boolean { switch (token()) { case SyntaxKind.OpenParenToken: // foo( - // this case are the only case where this token can legally follow a type argument - // list. So we definitely want to treat this as a type arg list. + case SyntaxKind.NoSubstitutionTemplateLiteral: // foo `...` + case SyntaxKind.TemplateHead: // foo `...${100}...` + // these are the only tokens can legally follow a type argument + // list. So we definitely want to treat them as type arg lists. case SyntaxKind.DotToken: // foo. case SyntaxKind.CloseParenToken: // foo) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 987d403e7cd..f96ea05cb12 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1726,6 +1726,7 @@ namespace ts { export interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } From 090f6bd77c53f2fe945dfefba69a1f7a99fe6ab8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:23:05 -0700 Subject: [PATCH 14/62] Accepted baselines. --- .../reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + ...ggedTemplatesWithTypeArguments1.errors.txt | 92 ++++++----- .../taggedTemplatesWithTypeArguments1.js | 34 ++-- .../taggedTemplatesWithTypeArguments1.symbols | 62 +++++-- .../taggedTemplatesWithTypeArguments1.types | 155 ++++++++++-------- 6 files changed, 204 insertions(+), 141 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2e8e3f3871d..ae99f93ae1a 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1050,6 +1050,7 @@ declare namespace ts { interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 378949d5b5b..c419eceaf95 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1050,6 +1050,7 @@ declare namespace ts { interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt index 700c98d54fe..6b732dbf4aa 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt @@ -1,16 +1,18 @@ -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(9,18): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(9,20): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(22,20): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(22,50): error TS1005: ',' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,18): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,30): error TS2693: 'Stuff' only refers to a type, but is being used as a value here. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,53): error TS1128: Declaration or statement expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(40,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(41,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(42,3): error TS2339: Property 'returnedProp' does not exist on type 'boolean'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(11,22): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(13,22): error TS2339: Property 'y' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(15,22): error TS2339: Property 'z' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(24,22): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(26,22): error TS2339: Property 'y' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(28,22): error TS2339: Property 'z' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(38,19): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,19): error TS2339: Property 'y' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(40,19): error TS2339: Property 'z' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(43,19): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(44,19): error TS2339: Property 'y' does not exist on type '{}'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(45,19): error TS2339: Property 'z' does not exist on type '{}'. -==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts (10 errors) ==== +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts (12 errors) ==== declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; interface Stuff { @@ -20,63 +22,63 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(42,3) } export const a = f ` - ~~~~~~~~~~ - ~~~~~ -!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. hello - ~~~~~~~~~ ${stuff => stuff.x} - ~~~~~~~~~~~~~~~~~~~~~~~ + ~ +!!! error TS2339: Property 'x' does not exist on type '{}'. brave - ~~~~~~~~~ ${stuff => stuff.y} - ~~~~~~~~~~~~~~~~~~~~~~~ + ~ +!!! error TS2339: Property 'y' does not exist on type '{}'. world - ~~~~~~~~~ ${stuff => stuff.z} - ~~~~~~~~~~~~~~~~~~~~~~~ + ~ +!!! error TS2339: Property 'z' does not exist on type '{}'. `; - ~ -!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. declare function g( strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; export const b = g ` - ~~~~~ -!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. - ~ -!!! error TS1005: ',' expected. hello ${stuff => stuff.x} + ~ +!!! error TS2339: Property 'x' does not exist on type '{}'. brave ${stuff => stuff.y} + ~ +!!! error TS2339: Property 'y' does not exist on type '{}'. world ${stuff => stuff.z} + ~ +!!! error TS2339: Property 'z' does not exist on type '{}'. `; declare let obj: { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { - returnedObjProp: { - lastOne: T - } + returnedObjProp: T } } - export const c = obj["prop"] `${(input) => { ...input }}` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'string'. - ~~~~~ -!!! error TS2693: 'Stuff' only refers to a type, but is being used as a value here. - ~~~ -!!! error TS1128: Declaration or statement expected. - c.returnedProp.x; - ~~~~~~~~~~~~ -!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. - c.returnedProp.y; - ~~~~~~~~~~~~ -!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. - c.returnedProp.z; - ~~~~~~~~~~~~ -!!! error TS2339: Property 'returnedProp' does not exist on type 'boolean'. \ No newline at end of file + export let c = obj["prop"] `${(input) => ({ ...input })}` + c.returnedObjProp.x; + ~ +!!! error TS2339: Property 'x' does not exist on type '{}'. + c.returnedObjProp.y; + ~ +!!! error TS2339: Property 'y' does not exist on type '{}'. + c.returnedObjProp.z; + ~ +!!! error TS2339: Property 'z' does not exist on type '{}'. + + c = obj.prop `${(input) => ({ ...input })}` + c.returnedObjProp.x; + ~ +!!! error TS2339: Property 'x' does not exist on type '{}'. + c.returnedObjProp.y; + ~ +!!! error TS2339: Property 'y' does not exist on type '{}'. + c.returnedObjProp.z; + ~ +!!! error TS2339: Property 'z' does not exist on type '{}'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js index 629571b4db0..9d2474da8be 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js @@ -31,19 +31,22 @@ export const b = g ` declare let obj: { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { - returnedObjProp: { - lastOne: T - } + returnedObjProp: T } } -export const c = obj["prop"] `${(input) => { ...input }}` -c.returnedProp.x; -c.returnedProp.y; -c.returnedProp.z; +export let c = obj["prop"] `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; + +c = obj.prop `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; //// [taggedTemplatesWithTypeArguments1.js] -export const a = f < Stuff > ` +export const a = f ` hello ${stuff => stuff.x} brave @@ -51,8 +54,7 @@ export const a = f < Stuff > ` world ${stuff => stuff.z} `; -export const b = g < Stuff, number, string, boolean; - > ` +export const b = g ` hello ${stuff => stuff.x} brave @@ -60,7 +62,11 @@ export const b = g < Stuff, number, string, boolean; world ${stuff => stuff.z} `; -export const c = obj["prop"] < Stuff > `${(input) => { input; }}`; -c.returnedProp.x; -c.returnedProp.y; -c.returnedProp.z; +export let c = obj["prop"] `${(input) => ({ ...input })}`; +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; +c = obj.prop `${(input) => ({ ...input })}`; +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols index 85170aad228..c90089e50cc 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols @@ -25,6 +25,7 @@ interface Stuff { export const a = f ` >a : Symbol(a, Decl(taggedTemplatesWithTypeArguments1.ts, 8, 12)) >f : Symbol(f, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 0)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) hello ${stuff => stuff.x} @@ -74,9 +75,7 @@ declare function g( export const b = g ` >b : Symbol(b, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 12)) >g : Symbol(g, Decl(taggedTemplatesWithTypeArguments1.ts, 15, 2)) ->number : Symbol(number, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 25)) ->string : Symbol(string, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 33)) ->boolean : Symbol(boolean, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 41)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) hello ${stuff => stuff.x} @@ -108,29 +107,56 @@ declare let obj: { >T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) >T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) - returnedObjProp: { + returnedObjProp: T >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) - - lastOne: T ->lastOne : Symbol(lastOne, Decl(taggedTemplatesWithTypeArguments1.ts, 32, 26)) >T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) - } } } -export const c = obj["prop"] `${(input) => { ...input }}` ->c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +export let c = obj["prop"] `${(input) => ({ ...input })}` +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) >"prop" : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) ->input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 40)) ->input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 40)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 38)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 38)) -c.returnedProp.x; ->c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +c.returnedObjProp.x; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) -c.returnedProp.y; ->c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +c.returnedObjProp.y; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) -c.returnedProp.z; ->c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 38, 12)) +c.returnedObjProp.z; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) + +c = obj.prop `${(input) => ({ ...input })}` +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>obj.prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) +>prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 41, 24)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 41, 24)) + +c.returnedObjProp.x; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) + +c.returnedObjProp.y; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) + +c.returnedObjProp.z; +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types index 9999bb67bd8..74f916d0efa 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types @@ -23,35 +23,34 @@ interface Stuff { } export const a = f ` ->a : boolean ->f ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : boolean ->fa : void +>f ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : void >f : (strs: TemplateStringsArray, ...callbacks: ((x: T) => any)[]) => void ->Stuff : any +>Stuff : Stuff >` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string hello ${stuff => stuff.x} ->stuff => stuff.x : (stuff: any) => any ->stuff : any +>stuff => stuff.x : (stuff: {}) => any +>stuff : {} >stuff.x : any ->stuff : any +>stuff : {} >x : any brave ${stuff => stuff.y} ->stuff => stuff.y : (stuff: any) => any ->stuff : any +>stuff => stuff.y : (stuff: {}) => any +>stuff : {} >stuff.y : any ->stuff : any +>stuff : {} >y : any world ${stuff => stuff.z} ->stuff => stuff.z : (stuff: any) => any ->stuff : any +>stuff => stuff.z : (stuff: {}) => any +>stuff : {} >stuff.z : any ->stuff : any +>stuff : {} >z : any `; @@ -85,48 +84,43 @@ declare function g( >V : V export const b = g ` ->b : boolean ->gb : any +>g ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : any >g : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V ->Stuff : any ->number : any ->string : any ->boolean : any ->> ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : boolean -> : any +>Stuff : Stuff >` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string hello ${stuff => stuff.x} ->stuff => stuff.x : (stuff: any) => any ->stuff : any +>stuff => stuff.x : (stuff: {}) => any +>stuff : {} >stuff.x : any ->stuff : any +>stuff : {} >x : any brave ${stuff => stuff.y} ->stuff => stuff.y : (stuff: any) => any ->stuff : any +>stuff => stuff.y : (stuff: {}) => any +>stuff : {} >stuff.y : any ->stuff : any +>stuff : {} >y : any world ${stuff => stuff.z} ->stuff => stuff.z : (stuff: any) => any ->stuff : any +>stuff => stuff.z : (stuff: {}) => any +>stuff : {} >stuff.z : any ->stuff : any +>stuff : {} >z : any `; declare let obj: { ->obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; }; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } prop: (strs: TemplateStringsArray, x: (input: T) => T) => { ->prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; } +>prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } >T : T >strs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray @@ -135,47 +129,80 @@ declare let obj: { >T : T >T : T - returnedObjProp: { ->returnedObjProp : { lastOne: T; } - - lastOne: T ->lastOne : T + returnedObjProp: T +>returnedObjProp : T >T : T - } } } -export const c = obj["prop"] `${(input) => { ...input }}` ->c : boolean ->obj["prop"] `${(input) => { ...input }}` : boolean ->obj["prop"]obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; } ->obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: { lastOne: T; }; }; } +export let c = obj["prop"] `${(input) => ({ ...input })}` +>c : { returnedObjProp: {}; } +>obj["prop"] `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } >"prop" : "prop" ->Stuff : any ->`${(input) => { ...input }}` : string ->(input) => { ...input } : (input: any) => void ->input : any ->input : any +>Stuff : Stuff +>`${(input) => ({ ...input })}` : string +>(input) => ({ ...input }) : (input: {}) => {} +>input : {} +>({ ...input }) : {} +>{ ...input } : {} +>input : {} -c.returnedProp.x; ->c.returnedProp.x : any ->c.returnedProp : any ->c : boolean ->returnedProp : any +c.returnedObjProp.x; +>c.returnedObjProp.x : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} >x : any -c.returnedProp.y; ->c.returnedProp.y : any ->c.returnedProp : any ->c : boolean ->returnedProp : any +c.returnedObjProp.y; +>c.returnedObjProp.y : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} >y : any -c.returnedProp.z; ->c.returnedProp.z : any ->c.returnedProp : any ->c : boolean ->returnedProp : any +c.returnedObjProp.z; +>c.returnedObjProp.z : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} +>z : any + +c = obj.prop `${(input) => ({ ...input })}` +>c = obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>c : { returnedObjProp: {}; } +>obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>obj.prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } +>prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>Stuff : Stuff +>`${(input) => ({ ...input })}` : string +>(input) => ({ ...input }) : (input: {}) => {} +>input : {} +>({ ...input }) : {} +>{ ...input } : {} +>input : {} + +c.returnedObjProp.x; +>c.returnedObjProp.x : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} +>x : any + +c.returnedObjProp.y; +>c.returnedObjProp.y : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} +>y : any + +c.returnedObjProp.z; +>c.returnedObjProp.z : any +>c.returnedObjProp : {} +>c : { returnedObjProp: {}; } +>returnedObjProp : {} >z : any From 7aa916a5cb477e1c7a6361c642770d67bb38c4c6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:35:32 -0700 Subject: [PATCH 15/62] Strip away type arguments from tagged templates when emitting. --- src/compiler/factory.ts | 8 +++++--- src/compiler/transformers/ts.ts | 11 +++++++++++ src/compiler/visitor.ts | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 765c3c9cb4a..7dd7216725a 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1032,17 +1032,19 @@ namespace ts { : node; } - export function createTaggedTemplate(tag: Expression, template: TemplateLiteral) { + export function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral) { const node = createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizeForAccess(tag); + node.typeArguments = typeArguments; node.template = template; return node; } - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral) { + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral) { return node.tag !== tag + || node.typeArguments !== typeArguments || node.template !== template - ? updateNode(createTaggedTemplate(tag, template), node) + ? updateNode(createTaggedTemplate(tag, typeArguments, template), node) : node; } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 6cb4be16c74..f29829d4607 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -502,6 +502,9 @@ namespace ts { case SyntaxKind.NewExpression: return visitNewExpression(node); + case SyntaxKind.TaggedTemplateExpression: + return visitTaggedTemplateExpression(node); + case SyntaxKind.NonNullExpression: // TypeScript non-null expressions are removed, but their subtrees are preserved. return visitNonNullExpression(node); @@ -2547,6 +2550,14 @@ namespace ts { visitNodes(node.arguments, visitor, isExpression)); } + function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { + return updateTaggedTemplate( + node, + visitNode(node.tag, visitor, isExpression), + /*typeArguments*/ undefined, + visitNode(node.template, visitor, isExpression)); + } + /** * Determines whether to emit an enum declaration. * diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 7a70eb02e8e..284d870caa1 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -478,6 +478,7 @@ namespace ts { case SyntaxKind.TaggedTemplateExpression: return updateTaggedTemplate(node, visitNode((node).tag, visitor, isExpression), + visitNodes((node).typeArguments, visitor, isExpression), visitNode((node).template, visitor, isTemplateLiteral)); case SyntaxKind.TypeAssertionExpression: From 4785acb8cd6a5529c77e26320a98b5aaee962cb6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:35:42 -0700 Subject: [PATCH 16/62] Accepted baselines. --- tests/baselines/reference/api/tsserverlibrary.d.ts | 4 ++-- tests/baselines/reference/api/typescript.d.ts | 4 ++-- .../reference/taggedTemplatesWithTypeArguments1.js | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ae99f93ae1a..a250dcf6961 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3517,8 +3517,8 @@ declare namespace ts { function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; - function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index c419eceaf95..4e15b26a13d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3517,8 +3517,8 @@ declare namespace ts { function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; - function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js index 9d2474da8be..b31d3270208 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js @@ -46,7 +46,7 @@ c.returnedObjProp.y; c.returnedObjProp.z; //// [taggedTemplatesWithTypeArguments1.js] -export const a = f ` +export const a = f ` hello ${stuff => stuff.x} brave @@ -54,7 +54,7 @@ export const a = f ` world ${stuff => stuff.z} `; -export const b = g ` +export const b = g ` hello ${stuff => stuff.x} brave @@ -62,11 +62,11 @@ export const b = g ` world ${stuff => stuff.z} `; -export let c = obj["prop"] `${(input) => ({ ...input })}`; +export let c = obj["prop"] `${(input) => ({ ...input })}`; c.returnedObjProp.x; c.returnedObjProp.y; c.returnedObjProp.z; -c = obj.prop `${(input) => ({ ...input })}`; +c = obj.prop `${(input) => ({ ...input })}`; c.returnedObjProp.x; c.returnedObjProp.y; c.returnedObjProp.z; From 82e09c908e3cf80cea12d2eb05a458a9a2b87811 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:43:49 -0700 Subject: [PATCH 17/62] Perform checking and resolution of tagged template type arguments. --- src/compiler/checker.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d009a956c43..60fcf103041 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17749,7 +17749,11 @@ namespace ts { let typeArguments: NodeArray; - if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) { + if (isTaggedTemplate) { + typeArguments = (node as TaggedTemplateExpression).typeArguments; + forEach(typeArguments, checkSourceElement); + } + else if (!isDecorator && !isJsxOpeningOrSelfClosingElement) { typeArguments = (node).typeArguments; // We already perform checking on the type arguments on the class declaration itself. @@ -17866,7 +17870,7 @@ namespace ts { checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression).typeArguments, /*reportErrors*/ true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression).typeArguments, /*reportErrors*/ true, fallbackError); } else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments.length)) { diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments)); @@ -18660,6 +18664,7 @@ namespace ts { } function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type { + checkGrammarTypeArguments(node, node.typeArguments); if (languageVersion < ScriptTarget.ES2015) { checkExternalEmitHelpers(node, ExternalEmitHelpers.MakeTemplateObject); } From fe8615d0a8ebbffc55a5f177d638f46259e57bb7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Apr 2018 23:44:07 -0700 Subject: [PATCH 18/62] Accepted baselines. --- ...ggedTemplatesWithTypeArguments1.errors.txt | 84 ---------- .../taggedTemplatesWithTypeArguments1.symbols | 24 +++ .../taggedTemplatesWithTypeArguments1.types | 154 +++++++++--------- 3 files changed, 101 insertions(+), 161 deletions(-) delete mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt deleted file mode 100644 index 6b732dbf4aa..00000000000 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.errors.txt +++ /dev/null @@ -1,84 +0,0 @@ -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(11,22): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(13,22): error TS2339: Property 'y' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(15,22): error TS2339: Property 'z' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(24,22): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(26,22): error TS2339: Property 'y' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(28,22): error TS2339: Property 'z' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(38,19): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(39,19): error TS2339: Property 'y' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(40,19): error TS2339: Property 'z' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(43,19): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(44,19): error TS2339: Property 'y' does not exist on type '{}'. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts(45,19): error TS2339: Property 'z' does not exist on type '{}'. - - -==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts (12 errors) ==== - declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; - - interface Stuff { - x: number; - y: string; - z: boolean; - } - - export const a = f ` - hello - ${stuff => stuff.x} - ~ -!!! error TS2339: Property 'x' does not exist on type '{}'. - brave - ${stuff => stuff.y} - ~ -!!! error TS2339: Property 'y' does not exist on type '{}'. - world - ${stuff => stuff.z} - ~ -!!! error TS2339: Property 'z' does not exist on type '{}'. - `; - - declare function g( - strs: TemplateStringsArray, - t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; - - export const b = g ` - hello - ${stuff => stuff.x} - ~ -!!! error TS2339: Property 'x' does not exist on type '{}'. - brave - ${stuff => stuff.y} - ~ -!!! error TS2339: Property 'y' does not exist on type '{}'. - world - ${stuff => stuff.z} - ~ -!!! error TS2339: Property 'z' does not exist on type '{}'. - `; - - declare let obj: { - prop: (strs: TemplateStringsArray, x: (input: T) => T) => { - returnedObjProp: T - } - } - - export let c = obj["prop"] `${(input) => ({ ...input })}` - c.returnedObjProp.x; - ~ -!!! error TS2339: Property 'x' does not exist on type '{}'. - c.returnedObjProp.y; - ~ -!!! error TS2339: Property 'y' does not exist on type '{}'. - c.returnedObjProp.z; - ~ -!!! error TS2339: Property 'z' does not exist on type '{}'. - - c = obj.prop `${(input) => ({ ...input })}` - c.returnedObjProp.x; - ~ -!!! error TS2339: Property 'x' does not exist on type '{}'. - c.returnedObjProp.y; - ~ -!!! error TS2339: Property 'y' does not exist on type '{}'. - c.returnedObjProp.z; - ~ -!!! error TS2339: Property 'z' does not exist on type '{}'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols index c90089e50cc..798d2e18c68 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols @@ -30,17 +30,23 @@ export const a = f ` hello ${stuff => stuff.x} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) +>stuff.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) brave ${stuff => stuff.y} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) +>stuff.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) world ${stuff => stuff.z} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) +>stuff.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) `; @@ -80,17 +86,23 @@ export const b = g ` hello ${stuff => stuff.x} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) +>stuff.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) brave ${stuff => stuff.y} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) +>stuff.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) world ${stuff => stuff.z} >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) +>stuff.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) >stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) `; @@ -122,19 +134,25 @@ export let c = obj["prop"] `${(input) => ({ ...input })}` >input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 38)) c.returnedObjProp.x; +>c.returnedObjProp.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) c.returnedObjProp.y; +>c.returnedObjProp.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) c.returnedObjProp.z; +>c.returnedObjProp.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) c = obj.prop `${(input) => ({ ...input })}` >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) @@ -146,17 +164,23 @@ c = obj.prop `${(input) => ({ ...input })}` >input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 41, 24)) c.returnedObjProp.x; +>c.returnedObjProp.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) c.returnedObjProp.y; +>c.returnedObjProp.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) c.returnedObjProp.z; +>c.returnedObjProp.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) >c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) >c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) >returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types index 74f916d0efa..afa83c1b890 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types @@ -31,27 +31,27 @@ export const a = f ` hello ${stuff => stuff.x} ->stuff => stuff.x : (stuff: {}) => any ->stuff : {} ->stuff.x : any ->stuff : {} ->x : any +>stuff => stuff.x : (stuff: Stuff) => number +>stuff : Stuff +>stuff.x : number +>stuff : Stuff +>x : number brave ${stuff => stuff.y} ->stuff => stuff.y : (stuff: {}) => any ->stuff : {} ->stuff.y : any ->stuff : {} ->y : any +>stuff => stuff.y : (stuff: Stuff) => string +>stuff : Stuff +>stuff.y : string +>stuff : Stuff +>y : string world ${stuff => stuff.z} ->stuff => stuff.z : (stuff: {}) => any ->stuff : {} ->stuff.z : any ->stuff : {} ->z : any +>stuff => stuff.z : (stuff: Stuff) => boolean +>stuff : Stuff +>stuff.z : boolean +>stuff : Stuff +>z : boolean `; @@ -84,35 +84,35 @@ declare function g( >V : V export const b = g ` ->b : any ->g ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : any +>b : string | number | boolean +>g ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string | number | boolean >g : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V >Stuff : Stuff >` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string hello ${stuff => stuff.x} ->stuff => stuff.x : (stuff: {}) => any ->stuff : {} ->stuff.x : any ->stuff : {} ->x : any +>stuff => stuff.x : (stuff: Stuff) => number +>stuff : Stuff +>stuff.x : number +>stuff : Stuff +>x : number brave ${stuff => stuff.y} ->stuff => stuff.y : (stuff: {}) => any ->stuff : {} ->stuff.y : any ->stuff : {} ->y : any +>stuff => stuff.y : (stuff: Stuff) => string +>stuff : Stuff +>stuff.y : string +>stuff : Stuff +>y : string world ${stuff => stuff.z} ->stuff => stuff.z : (stuff: {}) => any ->stuff : {} ->stuff.z : any ->stuff : {} ->z : any +>stuff => stuff.z : (stuff: Stuff) => boolean +>stuff : Stuff +>stuff.z : boolean +>stuff : Stuff +>z : boolean `; @@ -136,73 +136,73 @@ declare let obj: { } export let c = obj["prop"] `${(input) => ({ ...input })}` ->c : { returnedObjProp: {}; } ->obj["prop"] `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>c : { returnedObjProp: Stuff; } +>obj["prop"] `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } >obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } >obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } >"prop" : "prop" >Stuff : Stuff >`${(input) => ({ ...input })}` : string ->(input) => ({ ...input }) : (input: {}) => {} ->input : {} ->({ ...input }) : {} ->{ ...input } : {} ->input : {} +>(input) => ({ ...input }) : (input: Stuff) => { x: number; y: string; z: boolean; } +>input : Stuff +>({ ...input }) : { x: number; y: string; z: boolean; } +>{ ...input } : { x: number; y: string; z: boolean; } +>input : Stuff c.returnedObjProp.x; ->c.returnedObjProp.x : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->x : any +>c.returnedObjProp.x : number +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>x : number c.returnedObjProp.y; ->c.returnedObjProp.y : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->y : any +>c.returnedObjProp.y : string +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>y : string c.returnedObjProp.z; ->c.returnedObjProp.z : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->z : any +>c.returnedObjProp.z : boolean +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>z : boolean c = obj.prop `${(input) => ({ ...input })}` ->c = obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: {}; } ->c : { returnedObjProp: {}; } ->obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: {}; } +>c = obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } +>c : { returnedObjProp: Stuff; } +>obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } >obj.prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } >obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } >prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } >Stuff : Stuff >`${(input) => ({ ...input })}` : string ->(input) => ({ ...input }) : (input: {}) => {} ->input : {} ->({ ...input }) : {} ->{ ...input } : {} ->input : {} +>(input) => ({ ...input }) : (input: Stuff) => { x: number; y: string; z: boolean; } +>input : Stuff +>({ ...input }) : { x: number; y: string; z: boolean; } +>{ ...input } : { x: number; y: string; z: boolean; } +>input : Stuff c.returnedObjProp.x; ->c.returnedObjProp.x : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->x : any +>c.returnedObjProp.x : number +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>x : number c.returnedObjProp.y; ->c.returnedObjProp.y : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->y : any +>c.returnedObjProp.y : string +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>y : string c.returnedObjProp.z; ->c.returnedObjProp.z : any ->c.returnedObjProp : {} ->c : { returnedObjProp: {}; } ->returnedObjProp : {} ->z : any +>c.returnedObjProp.z : boolean +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>z : boolean From 299002d597eed0daa56a444730ea5cdaff682ac3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sat, 14 Apr 2018 11:53:27 -0700 Subject: [PATCH 19/62] Fix spacing. --- src/compiler/commandLineParser.ts | 16 ++++++++-------- src/compiler/tsc.ts | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 252ea9e8df0..2de922b4159 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -56,14 +56,14 @@ namespace ts { category: Diagnostics.Command_line_Options, description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental }, - { - name: "diagnosticStyle", - type: createMapFromTemplate({ - auto: DiagnosticStyle.Auto, - pretty: DiagnosticStyle.Pretty, - simple: DiagnosticStyle.Simple, - }), - }, + { + name: "diagnosticStyle", + type: createMapFromTemplate({ + auto: DiagnosticStyle.Auto, + pretty: DiagnosticStyle.Pretty, + simple: DiagnosticStyle.Simple, + }), + }, { name: "preserveWatchOutput", type: "boolean", diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 5012b73e98a..56c3c323f30 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -27,7 +27,7 @@ namespace ts { function shouldBePretty(options: CompilerOptions) { if ((typeof options.pretty === "undefined" && typeof options.diagnosticStyle === "undefined") || options.diagnosticStyle === DiagnosticStyle.Auto) { return !!sys.writeOutputIsTty && sys.writeOutputIsTty(); - } + } return options.diagnosticStyle === DiagnosticStyle.Pretty || options.pretty; } From 6107e05e8cdeefc598d49ec10f21c61dc325a0e2 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 15 Apr 2018 15:56:59 -0700 Subject: [PATCH 20/62] Added test for tagged templates in new expressions. --- .../taggedTemplatesWithTypeArguments2.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts new file mode 100644 index 00000000000..9c9bb8ee938 --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts @@ -0,0 +1,20 @@ +// @target: esnext +// @strict: true + +export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +} + +export interface SomethingNewable { + new (...args: T[]): any; +} + +declare const tag: SomethingTaggable; + +const a = new tag `${100} ${200}`("hello", "world"); + +const b = new tag `${"hello"} ${"world"}`(100, 200); + +const c = new tag `${100} ${200}`("hello", "world"); + +const d = new tag `${"hello"} ${"world"}`(100, 200); From 2510c19fbd64baba32d9b4c656c9902163fb10d7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 15 Apr 2018 15:59:23 -0700 Subject: [PATCH 21/62] Accepted baselines. --- ...ggedTemplatesWithTypeArguments2.errors.txt | 66 +++++++++++++++++ .../taggedTemplatesWithTypeArguments2.js | 25 +++++++ .../taggedTemplatesWithTypeArguments2.symbols | 42 +++++++++++ .../taggedTemplatesWithTypeArguments2.types | 70 +++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments2.js create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols create mode 100644 tests/baselines/reference/taggedTemplatesWithTypeArguments2.types diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt new file mode 100644 index 00000000000..958fb6715d1 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -0,0 +1,66 @@ +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,11): error TS2350: Only a void function can be called with the 'new' keyword. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,27): error TS1005: '(' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,60): error TS1005: ')' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2350: Only a void function can be called with the 'new' keyword. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,27): error TS1005: '(' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,68): error TS1005: ')' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,11): error TS2350: Only a void function can be called with the 'new' keyword. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,27): error TS1005: '(' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,68): error TS1005: ')' expected. + + +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (15 errors) ==== + export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; + } + + export interface SomethingNewable { + new (...args: T[]): any; + } + + declare const tag: SomethingTaggable; + + const a = new tag `${100} ${200}`("hello", "world"); + + const b = new tag `${"hello"} ${"world"}`(100, 200); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2350: Only a void function can be called with the 'new' keyword. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. + ~~~ +!!! error TS1005: '(' expected. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + ~ +!!! error TS1005: ')' expected. + + const c = new tag `${100} ${200}`("hello", "world"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2350: Only a void function can be called with the 'new' keyword. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. + ~~~ +!!! error TS1005: '(' expected. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + ~ +!!! error TS1005: ')' expected. + + const d = new tag `${"hello"} ${"world"}`(100, 200); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2350: Only a void function can be called with the 'new' keyword. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. + ~~~ +!!! error TS1005: '(' expected. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + ~ +!!! error TS1005: ')' expected. + \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js new file mode 100644 index 00000000000..3d2012eb0ac --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -0,0 +1,25 @@ +//// [taggedTemplatesWithTypeArguments2.ts] +export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +} + +export interface SomethingNewable { + new (...args: T[]): any; +} + +declare const tag: SomethingTaggable; + +const a = new tag `${100} ${200}`("hello", "world"); + +const b = new tag `${"hello"} ${"world"}`(100, 200); + +const c = new tag `${100} ${200}`("hello", "world"); + +const d = new tag `${"hello"} ${"world"}`(100, 200); + + +//// [taggedTemplatesWithTypeArguments2.js] +const a = new tag `${100} ${200}`("hello", "world"); +const b = new tag(`${"hello"} ${"world"}`(100, 200)); +const c = new tag(`${100} ${200}`("hello", "world")); +const d = new tag(`${"hello"} ${"world"}`(100, 200)); diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols new file mode 100644 index 00000000000..720b03dd325 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols @@ -0,0 +1,42 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts === +export interface SomethingTaggable { +>SomethingTaggable : Symbol(SomethingTaggable, Decl(taggedTemplatesWithTypeArguments2.ts, 0, 0)) + + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 5)) +>t : Symbol(t, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 8)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 32)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 5)) +>SomethingNewable : Symbol(SomethingNewable, Decl(taggedTemplatesWithTypeArguments2.ts, 2, 1)) +} + +export interface SomethingNewable { +>SomethingNewable : Symbol(SomethingNewable, Decl(taggedTemplatesWithTypeArguments2.ts, 2, 1)) + + new (...args: T[]): any; +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 9)) +>args : Symbol(args, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 12)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 9)) +} + +declare const tag: SomethingTaggable; +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) +>SomethingTaggable : Symbol(SomethingTaggable, Decl(taggedTemplatesWithTypeArguments2.ts, 0, 0)) + +const a = new tag `${100} ${200}`("hello", "world"); +>a : Symbol(a, Decl(taggedTemplatesWithTypeArguments2.ts, 10, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const b = new tag `${"hello"} ${"world"}`(100, 200); +>b : Symbol(b, Decl(taggedTemplatesWithTypeArguments2.ts, 12, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const c = new tag `${100} ${200}`("hello", "world"); +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments2.ts, 14, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const d = new tag `${"hello"} ${"world"}`(100, 200); +>d : Symbol(d, Decl(taggedTemplatesWithTypeArguments2.ts, 16, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types new file mode 100644 index 00000000000..bc05e62fcdc --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -0,0 +1,70 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts === +export interface SomethingTaggable { +>SomethingTaggable : SomethingTaggable + + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +>T : T +>t : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>args : T[] +>T : T +>SomethingNewable : SomethingNewable +} + +export interface SomethingNewable { +>SomethingNewable : SomethingNewable + + new (...args: T[]): any; +>T : T +>args : T[] +>T : T +} + +declare const tag: SomethingTaggable; +>tag : SomethingTaggable +>SomethingTaggable : SomethingTaggable + +const a = new tag `${100} ${200}`("hello", "world"); +>a : any +>new tag `${100} ${200}`("hello", "world") : any +>tag `${100} ${200}` : SomethingNewable +>tag : SomethingTaggable +>`${100} ${200}` : string +>100 : 100 +>200 : 200 +>"hello" : "hello" +>"world" : "world" + +const b = new tag `${"hello"} ${"world"}`(100, 200); +>b : any +>new tag `${"hello"} ${"world"}`(100, 200) : any +>tag : SomethingTaggable +>`${"hello"} ${"world"}`(100, 200) : any +>`${"hello"} ${"world"}` : string +>"hello" : "hello" +>"world" : "world" +>100 : 100 +>200 : 200 + +const c = new tag `${100} ${200}`("hello", "world"); +>c : any +>new tag `${100} ${200}`("hello", "world") : any +>tag : SomethingTaggable +>`${100} ${200}`("hello", "world") : any +>`${100} ${200}` : string +>100 : 100 +>200 : 200 +>"hello" : "hello" +>"world" : "world" + +const d = new tag `${"hello"} ${"world"}`(100, 200); +>d : any +>new tag `${"hello"} ${"world"}`(100, 200) : any +>tag : SomethingTaggable +>`${"hello"} ${"world"}`(100, 200) : any +>`${"hello"} ${"world"}` : string +>"hello" : "hello" +>"world" : "world" +>100 : 100 +>200 : 200 + From eb8eeafc224758690e8e7fefec94ac0bde60efe9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 15 Apr 2018 16:04:25 -0700 Subject: [PATCH 22/62] Allow parsing tagged templates with type arguments in new expressions. --- src/compiler/parser.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 29d57c846f5..f5dd8fa764d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4684,9 +4684,23 @@ namespace ts { return finishNode(node); } + let expression: MemberExpression = parsePrimaryExpression(); + let typeArguments; + while (true) { + expression = parseMemberExpressionRest(expression); + typeArguments = tryParse(parseTypeArgumentsInExpression); + if (isTemplateStartOfTaggedTemplate()) { + Debug.assert(!!typeArguments, + "Expected a type argument list; all plain tagged template starts should be consumed in 'parseMemberExpressionRest'"); + expression = parseTaggedTemplateRest(expression, typeArguments); + typeArguments = undefined; + } + break; + } + const node = createNode(SyntaxKind.NewExpression, fullStart); - node.expression = parseMemberExpressionOrHigher(); - node.typeArguments = tryParse(parseTypeArgumentsInExpression); + node.expression = expression; + node.typeArguments = typeArguments; if (node.typeArguments || token() === SyntaxKind.OpenParenToken) { node.arguments = parseArgumentList(); } From a2073f121758a8c8478ebea80e99a52d0f124ca4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 15 Apr 2018 16:04:47 -0700 Subject: [PATCH 23/62] Accepted baselines. --- ...ggedTemplatesWithTypeArguments2.errors.txt | 54 ++++--------------- .../taggedTemplatesWithTypeArguments2.js | 6 +-- .../taggedTemplatesWithTypeArguments2.types | 8 +-- 3 files changed, 17 insertions(+), 51 deletions(-) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt index 958fb6715d1..51b8bd34e0c 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -1,21 +1,9 @@ -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,11): error TS2350: Only a void function can be called with the 'new' keyword. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,27): error TS1005: '(' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,60): error TS1005: ')' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2350: Only a void function can be called with the 'new' keyword. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,27): error TS1005: '(' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,68): error TS1005: ')' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,11): error TS2350: Only a void function can be called with the 'new' keyword. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,11): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,27): error TS1005: '(' expected. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,68): error TS1005: ')' expected. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2347: Untyped function calls may not accept type arguments. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. -==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (15 errors) ==== +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (3 errors) ==== export interface SomethingTaggable { (t: TemplateStringsArray, ...args: T[]): SomethingNewable; } @@ -29,38 +17,14 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,68 const a = new tag `${100} ${200}`("hello", "world"); const b = new tag `${"hello"} ${"world"}`(100, 200); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2350: Only a void function can be called with the 'new' keyword. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. - ~~~ -!!! error TS1005: '(' expected. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. - ~ -!!! error TS1005: ')' expected. + ~~~~~~~ +!!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. const c = new tag `${100} ${200}`("hello", "world"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2350: Only a void function can be called with the 'new' keyword. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. - ~~~ -!!! error TS1005: '(' expected. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. - ~ -!!! error TS1005: ')' expected. +!!! error TS2347: Untyped function calls may not accept type arguments. const d = new tag `${"hello"} ${"world"}`(100, 200); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2350: Only a void function can be called with the 'new' keyword. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. - ~~~ -!!! error TS1005: '(' expected. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. - ~ -!!! error TS1005: ')' expected. + ~~~~~~~ +!!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js index 3d2012eb0ac..33e9fef3d7f 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -20,6 +20,6 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); //// [taggedTemplatesWithTypeArguments2.js] const a = new tag `${100} ${200}`("hello", "world"); -const b = new tag(`${"hello"} ${"world"}`(100, 200)); -const c = new tag(`${100} ${200}`("hello", "world")); -const d = new tag(`${"hello"} ${"world"}`(100, 200)); +const b = new tag `${"hello"} ${"world"}`(100, 200); +const c = (new tag `${100} ${200}`)("hello", "world"); +const d = (new tag `${"hello"} ${"world"}`)(100, 200); diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types index bc05e62fcdc..cd4ff1c6e13 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -38,8 +38,8 @@ const a = new tag `${100} ${200}`("hello", "world"); const b = new tag `${"hello"} ${"world"}`(100, 200); >b : any >new tag `${"hello"} ${"world"}`(100, 200) : any +>tag `${"hello"} ${"world"}` : any >tag : SomethingTaggable ->`${"hello"} ${"world"}`(100, 200) : any >`${"hello"} ${"world"}` : string >"hello" : "hello" >"world" : "world" @@ -49,8 +49,9 @@ const b = new tag `${"hello"} ${"world"}`(100, 200); const c = new tag `${100} ${200}`("hello", "world"); >c : any >new tag `${100} ${200}`("hello", "world") : any +>new tag `${100} ${200}` : any +>tag `${100} ${200}` : SomethingNewable >tag : SomethingTaggable ->`${100} ${200}`("hello", "world") : any >`${100} ${200}` : string >100 : 100 >200 : 200 @@ -60,8 +61,9 @@ const c = new tag `${100} ${200}`("hello", "world"); const d = new tag `${"hello"} ${"world"}`(100, 200); >d : any >new tag `${"hello"} ${"world"}`(100, 200) : any +>new tag `${"hello"} ${"world"}` : any +>tag `${"hello"} ${"world"}` : any >tag : SomethingTaggable ->`${"hello"} ${"world"}`(100, 200) : any >`${"hello"} ${"world"}` : string >"hello" : "hello" >"world" : "world" From 6798d56472f656a2f9633963f8b99eae68286a7e Mon Sep 17 00:00:00 2001 From: falsandtru Date: Tue, 17 Apr 2018 23:08:06 +0900 Subject: [PATCH 24/62] Fix Promise.reject --- src/lib/es2015.promise.d.ts | 9 +- tests/baselines/reference/promiseType.symbols | 96 +++++++++---------- tests/baselines/reference/promiseType.types | 96 +++++++++---------- .../reference/promiseTypeStrictNull.symbols | 96 +++++++++---------- .../reference/promiseTypeStrictNull.types | 96 +++++++++---------- 5 files changed, 193 insertions(+), 200 deletions(-) diff --git a/src/lib/es2015.promise.d.ts b/src/lib/es2015.promise.d.ts index ab33531191f..14602c0b5ed 100644 --- a/src/lib/es2015.promise.d.ts +++ b/src/lib/es2015.promise.d.ts @@ -177,14 +177,7 @@ interface PromiseConstructor { * @param reason The reason the promise was rejected. * @returns A new rejected Promise. */ - reject(reason: any): Promise; - - /** - * Creates a new rejected promise for the provided reason. - * @param reason The reason the promise was rejected. - * @returns A new rejected Promise. - */ - reject(reason: any): Promise; + reject(reason?: any): Promise; /** * Creates a new resolved promise for the provided value. diff --git a/tests/baselines/reference/promiseType.symbols b/tests/baselines/reference/promiseType.symbols index 5eea680f9fb..f33d26b8506 100644 --- a/tests/baselines/reference/promiseType.symbols +++ b/tests/baselines/reference/promiseType.symbols @@ -91,9 +91,9 @@ async function F() { >e : Symbol(e, Decl(promiseType.ts, 47, 11)) return Promise.reject(Error()); ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) } } @@ -150,9 +150,9 @@ async function I() { >e : Symbol(e, Decl(promiseType.ts, 77, 11)) return Promise.reject(Error()); ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) } } @@ -227,9 +227,9 @@ const p18 = p.catch(() => Promise.reject(1)); >p.catch : Symbol(Promise.catch, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >catch : Symbol(Promise.catch, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p19 = p.catch(() => Promise.resolve(1)); >p19 : Symbol(p19, Decl(promiseType.ts, 96, 5)) @@ -305,9 +305,9 @@ const p29 = p.then(() => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p30 = p.then(undefined, undefined); >p30 : Symbol(p30, Decl(promiseType.ts, 109, 5)) @@ -384,9 +384,9 @@ const p39 = p.then(undefined, () => Promise.reject(1)); >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >undefined : Symbol(undefined) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p40 = p.then(null, undefined); >p40 : Symbol(p40, Decl(promiseType.ts, 120, 5)) @@ -453,9 +453,9 @@ const p49 = p.then(null, () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p50 = p.then(() => "1", undefined); >p50 : Symbol(p50, Decl(promiseType.ts, 131, 5)) @@ -522,9 +522,9 @@ const p59 = p.then(() => "1", () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p60 = p.then(() => x, undefined); >p60 : Symbol(p60, Decl(promiseType.ts, 142, 5)) @@ -601,9 +601,9 @@ const p69 = p.then(() => x, () => Promise.reject(1)); >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >x : Symbol(x, Decl(promiseType.ts, 1, 11)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p70 = p.then(() => undefined, undefined); >p70 : Symbol(p70, Decl(promiseType.ts, 153, 5)) @@ -680,9 +680,9 @@ const p79 = p.then(() => undefined, () => Promise.reject(1)); >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >undefined : Symbol(undefined) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p80 = p.then(() => null, undefined); >p80 : Symbol(p80, Decl(promiseType.ts, 164, 5)) @@ -749,9 +749,9 @@ const p89 = p.then(() => null, () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p90 = p.then(() => {}, undefined); >p90 : Symbol(p90, Decl(promiseType.ts, 175, 5)) @@ -818,9 +818,9 @@ const p99 = p.then(() => {}, () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pa0 = p.then(() => {throw 1}, undefined); >pa0 : Symbol(pa0, Decl(promiseType.ts, 186, 5)) @@ -887,9 +887,9 @@ const pa9 = p.then(() => {throw 1}, () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pb0 = p.then(() => Promise.resolve("1"), undefined); >pb0 : Symbol(pb0, Decl(promiseType.ts, 197, 5)) @@ -986,18 +986,18 @@ const pb9 = p.then(() => Promise.resolve("1"), () => Promise.reject(1)); >Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc0 = p.then(() => Promise.reject("1"), undefined); >pc0 : Symbol(pc0, Decl(promiseType.ts, 208, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >undefined : Symbol(undefined) const pc1 = p.then(() => Promise.reject("1"), null); @@ -1005,27 +1005,27 @@ const pc1 = p.then(() => Promise.reject("1"), null); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc2 = p.then(() => Promise.reject("1"), () => 1); >pc2 : Symbol(pc2, Decl(promiseType.ts, 210, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc3 = p.then(() => Promise.reject("1"), () => x); >pc3 : Symbol(pc3, Decl(promiseType.ts, 211, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >x : Symbol(x, Decl(promiseType.ts, 1, 11)) const pc4 = p.then(() => Promise.reject("1"), () => undefined); @@ -1033,9 +1033,9 @@ const pc4 = p.then(() => Promise.reject("1"), () => undefined); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >undefined : Symbol(undefined) const pc5 = p.then(() => Promise.reject("1"), () => null); @@ -1043,36 +1043,36 @@ const pc5 = p.then(() => Promise.reject("1"), () => null); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc6 = p.then(() => Promise.reject("1"), () => {}); >pc6 : Symbol(pc6, Decl(promiseType.ts, 214, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc7 = p.then(() => Promise.reject("1"), () => {throw 1}); >pc7 : Symbol(pc7, Decl(promiseType.ts, 215, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc8 = p.then(() => Promise.reject("1"), () => Promise.resolve(1)); >pc8 : Symbol(pc8, Decl(promiseType.ts, 216, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) @@ -1082,10 +1082,10 @@ const pc9 = p.then(() => Promise.reject("1"), () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseType.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) diff --git a/tests/baselines/reference/promiseType.types b/tests/baselines/reference/promiseType.types index 3228d266319..f5674143bb8 100644 --- a/tests/baselines/reference/promiseType.types +++ b/tests/baselines/reference/promiseType.types @@ -105,9 +105,9 @@ async function F() { return Promise.reject(Error()); >Promise.reject(Error()) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >Error() : Error >Error : ErrorConstructor } @@ -170,9 +170,9 @@ async function I() { return Promise.reject(Error()); >Promise.reject(Error()) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >Error() : Error >Error : ErrorConstructor } @@ -271,9 +271,9 @@ const p18 = p.catch(() => Promise.reject(1)); >catch : (onrejected?: (reason: any) => TResult | PromiseLike) => Promise >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p19 = p.catch(() => Promise.resolve(1)); @@ -379,9 +379,9 @@ const p29 = p.then(() => Promise.reject(1)); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p30 = p.then(undefined, undefined); @@ -484,9 +484,9 @@ const p39 = p.then(undefined, () => Promise.reject(1)); >undefined : undefined >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p40 = p.then(null, undefined); @@ -589,9 +589,9 @@ const p49 = p.then(null, () => Promise.reject(1)); >null : null >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p50 = p.then(() => "1", undefined); @@ -704,9 +704,9 @@ const p59 = p.then(() => "1", () => Promise.reject(1)); >"1" : "1" >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p60 = p.then(() => x, undefined); @@ -819,9 +819,9 @@ const p69 = p.then(() => x, () => Promise.reject(1)); >x : any >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p70 = p.then(() => undefined, undefined); @@ -934,9 +934,9 @@ const p79 = p.then(() => undefined, () => Promise.reject(1)); >undefined : undefined >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p80 = p.then(() => null, undefined); @@ -1049,9 +1049,9 @@ const p89 = p.then(() => null, () => Promise.reject(1)); >null : null >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p90 = p.then(() => {}, undefined); @@ -1154,9 +1154,9 @@ const p99 = p.then(() => {}, () => Promise.reject(1)); >() => {} : () => void >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const pa0 = p.then(() => {throw 1}, undefined); @@ -1269,9 +1269,9 @@ const pa9 = p.then(() => {throw 1}, () => Promise.reject(1)); >1 : 1 >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const pb0 = p.then(() => Promise.resolve("1"), undefined); @@ -1424,9 +1424,9 @@ const pb9 = p.then(() => Promise.resolve("1"), () => Promise.reject(1)); >"1" : "1" >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const pc0 = p.then(() => Promise.reject("1"), undefined); @@ -1437,9 +1437,9 @@ const pc0 = p.then(() => Promise.reject("1"), undefined); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >undefined : undefined @@ -1451,9 +1451,9 @@ const pc1 = p.then(() => Promise.reject("1"), null); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >null : null @@ -1465,9 +1465,9 @@ const pc2 = p.then(() => Promise.reject("1"), () => 1); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => 1 : () => number >1 : 1 @@ -1480,9 +1480,9 @@ const pc3 = p.then(() => Promise.reject("1"), () => x); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => x : () => any >x : any @@ -1495,9 +1495,9 @@ const pc4 = p.then(() => Promise.reject("1"), () => undefined); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => undefined : () => any >undefined : undefined @@ -1510,9 +1510,9 @@ const pc5 = p.then(() => Promise.reject("1"), () => null); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => null : () => any >null : null @@ -1525,9 +1525,9 @@ const pc6 = p.then(() => Promise.reject("1"), () => {}); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => {} : () => void @@ -1539,9 +1539,9 @@ const pc7 = p.then(() => Promise.reject("1"), () => {throw 1}); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => {throw 1} : () => never >1 : 1 @@ -1554,9 +1554,9 @@ const pc8 = p.then(() => Promise.reject("1"), () => Promise.resolve(1)); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => Promise.resolve(1) : () => Promise >Promise.resolve(1) : Promise @@ -1573,14 +1573,14 @@ const pc9 = p.then(() => Promise.reject("1"), () => Promise.reject(1)); >then : (onfulfilled?: (value: boolean) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 diff --git a/tests/baselines/reference/promiseTypeStrictNull.symbols b/tests/baselines/reference/promiseTypeStrictNull.symbols index 3fabb7f16b7..30609978642 100644 --- a/tests/baselines/reference/promiseTypeStrictNull.symbols +++ b/tests/baselines/reference/promiseTypeStrictNull.symbols @@ -91,9 +91,9 @@ async function F() { >e : Symbol(e, Decl(promiseTypeStrictNull.ts, 47, 11)) return Promise.reject(Error()); ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) } } @@ -150,9 +150,9 @@ async function I() { >e : Symbol(e, Decl(promiseTypeStrictNull.ts, 77, 11)) return Promise.reject(Error()); ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) } } @@ -227,9 +227,9 @@ const p18 = p.catch(() => Promise.reject(1)); >p.catch : Symbol(Promise.catch, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >catch : Symbol(Promise.catch, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p19 = p.catch(() => Promise.resolve(1)); >p19 : Symbol(p19, Decl(promiseTypeStrictNull.ts, 96, 5)) @@ -305,9 +305,9 @@ const p29 = p.then(() => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p30 = p.then(undefined, undefined); >p30 : Symbol(p30, Decl(promiseTypeStrictNull.ts, 109, 5)) @@ -384,9 +384,9 @@ const p39 = p.then(undefined, () => Promise.reject(1)); >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >undefined : Symbol(undefined) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p40 = p.then(null, undefined); >p40 : Symbol(p40, Decl(promiseTypeStrictNull.ts, 120, 5)) @@ -453,9 +453,9 @@ const p49 = p.then(null, () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p50 = p.then(() => "1", undefined); >p50 : Symbol(p50, Decl(promiseTypeStrictNull.ts, 131, 5)) @@ -522,9 +522,9 @@ const p59 = p.then(() => "1", () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p60 = p.then(() => x, undefined); >p60 : Symbol(p60, Decl(promiseTypeStrictNull.ts, 142, 5)) @@ -601,9 +601,9 @@ const p69 = p.then(() => x, () => Promise.reject(1)); >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >x : Symbol(x, Decl(promiseTypeStrictNull.ts, 1, 11)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p70 = p.then(() => undefined, undefined); >p70 : Symbol(p70, Decl(promiseTypeStrictNull.ts, 153, 5)) @@ -680,9 +680,9 @@ const p79 = p.then(() => undefined, () => Promise.reject(1)); >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >undefined : Symbol(undefined) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p80 = p.then(() => null, undefined); >p80 : Symbol(p80, Decl(promiseTypeStrictNull.ts, 164, 5)) @@ -749,9 +749,9 @@ const p89 = p.then(() => null, () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const p90 = p.then(() => {}, undefined); >p90 : Symbol(p90, Decl(promiseTypeStrictNull.ts, 175, 5)) @@ -818,9 +818,9 @@ const p99 = p.then(() => {}, () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pa0 = p.then(() => {throw 1}, undefined); >pa0 : Symbol(pa0, Decl(promiseTypeStrictNull.ts, 186, 5)) @@ -887,9 +887,9 @@ const pa9 = p.then(() => {throw 1}, () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pb0 = p.then(() => Promise.resolve("1"), undefined); >pb0 : Symbol(pb0, Decl(promiseTypeStrictNull.ts, 197, 5)) @@ -986,18 +986,18 @@ const pb9 = p.then(() => Promise.resolve("1"), () => Promise.reject(1)); >Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc0 = p.then(() => Promise.reject("1"), undefined); >pc0 : Symbol(pc0, Decl(promiseTypeStrictNull.ts, 208, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >undefined : Symbol(undefined) const pc1 = p.then(() => Promise.reject("1"), null); @@ -1005,27 +1005,27 @@ const pc1 = p.then(() => Promise.reject("1"), null); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc2 = p.then(() => Promise.reject("1"), () => 1); >pc2 : Symbol(pc2, Decl(promiseTypeStrictNull.ts, 210, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc3 = p.then(() => Promise.reject("1"), () => x); >pc3 : Symbol(pc3, Decl(promiseTypeStrictNull.ts, 211, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >x : Symbol(x, Decl(promiseTypeStrictNull.ts, 1, 11)) const pc4 = p.then(() => Promise.reject("1"), () => undefined); @@ -1033,9 +1033,9 @@ const pc4 = p.then(() => Promise.reject("1"), () => undefined); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >undefined : Symbol(undefined) const pc5 = p.then(() => Promise.reject("1"), () => null); @@ -1043,36 +1043,36 @@ const pc5 = p.then(() => Promise.reject("1"), () => null); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc6 = p.then(() => Promise.reject("1"), () => {}); >pc6 : Symbol(pc6, Decl(promiseTypeStrictNull.ts, 214, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc7 = p.then(() => Promise.reject("1"), () => {throw 1}); >pc7 : Symbol(pc7, Decl(promiseTypeStrictNull.ts, 215, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) const pc8 = p.then(() => Promise.reject("1"), () => Promise.resolve(1)); >pc8 : Symbol(pc8, Decl(promiseTypeStrictNull.ts, 216, 5)) >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) @@ -1082,10 +1082,10 @@ const pc9 = p.then(() => Promise.reject("1"), () => Promise.reject(1)); >p.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) >p : Symbol(p, Decl(promiseTypeStrictNull.ts, 0, 11)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) +>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) ->reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --)) diff --git a/tests/baselines/reference/promiseTypeStrictNull.types b/tests/baselines/reference/promiseTypeStrictNull.types index 7bb75ec66f2..99c16c0b511 100644 --- a/tests/baselines/reference/promiseTypeStrictNull.types +++ b/tests/baselines/reference/promiseTypeStrictNull.types @@ -105,9 +105,9 @@ async function F() { return Promise.reject(Error()); >Promise.reject(Error()) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >Error() : Error >Error : ErrorConstructor } @@ -170,9 +170,9 @@ async function I() { return Promise.reject(Error()); >Promise.reject(Error()) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >Error() : Error >Error : ErrorConstructor } @@ -271,9 +271,9 @@ const p18 = p.catch(() => Promise.reject(1)); >catch : (onrejected?: ((reason: any) => TResult | PromiseLike) | null | undefined) => Promise >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p19 = p.catch(() => Promise.resolve(1)); @@ -379,9 +379,9 @@ const p29 = p.then(() => Promise.reject(1)); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p30 = p.then(undefined, undefined); @@ -484,9 +484,9 @@ const p39 = p.then(undefined, () => Promise.reject(1)); >undefined : undefined >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p40 = p.then(null, undefined); @@ -589,9 +589,9 @@ const p49 = p.then(null, () => Promise.reject(1)); >null : null >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p50 = p.then(() => "1", undefined); @@ -704,9 +704,9 @@ const p59 = p.then(() => "1", () => Promise.reject(1)); >"1" : "1" >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p60 = p.then(() => x, undefined); @@ -819,9 +819,9 @@ const p69 = p.then(() => x, () => Promise.reject(1)); >x : any >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p70 = p.then(() => undefined, undefined); @@ -934,9 +934,9 @@ const p79 = p.then(() => undefined, () => Promise.reject(1)); >undefined : undefined >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p80 = p.then(() => null, undefined); @@ -1049,9 +1049,9 @@ const p89 = p.then(() => null, () => Promise.reject(1)); >null : null >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const p90 = p.then(() => {}, undefined); @@ -1154,9 +1154,9 @@ const p99 = p.then(() => {}, () => Promise.reject(1)); >() => {} : () => void >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const pa0 = p.then(() => {throw 1}, undefined); @@ -1269,9 +1269,9 @@ const pa9 = p.then(() => {throw 1}, () => Promise.reject(1)); >1 : 1 >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const pb0 = p.then(() => Promise.resolve("1"), undefined); @@ -1424,9 +1424,9 @@ const pb9 = p.then(() => Promise.resolve("1"), () => Promise.reject(1)); >"1" : "1" >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 const pc0 = p.then(() => Promise.reject("1"), undefined); @@ -1437,9 +1437,9 @@ const pc0 = p.then(() => Promise.reject("1"), undefined); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >undefined : undefined @@ -1451,9 +1451,9 @@ const pc1 = p.then(() => Promise.reject("1"), null); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >null : null @@ -1465,9 +1465,9 @@ const pc2 = p.then(() => Promise.reject("1"), () => 1); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => 1 : () => number >1 : 1 @@ -1480,9 +1480,9 @@ const pc3 = p.then(() => Promise.reject("1"), () => x); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => x : () => any >x : any @@ -1495,9 +1495,9 @@ const pc4 = p.then(() => Promise.reject("1"), () => undefined); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => undefined : () => undefined >undefined : undefined @@ -1510,9 +1510,9 @@ const pc5 = p.then(() => Promise.reject("1"), () => null); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => null : () => null >null : null @@ -1525,9 +1525,9 @@ const pc6 = p.then(() => Promise.reject("1"), () => {}); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => {} : () => void @@ -1539,9 +1539,9 @@ const pc7 = p.then(() => Promise.reject("1"), () => {throw 1}); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => {throw 1} : () => never >1 : 1 @@ -1554,9 +1554,9 @@ const pc8 = p.then(() => Promise.reject("1"), () => Promise.resolve(1)); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => Promise.resolve(1) : () => Promise >Promise.resolve(1) : Promise @@ -1573,14 +1573,14 @@ const pc9 = p.then(() => Promise.reject("1"), () => Promise.reject(1)); >then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise >() => Promise.reject("1") : () => Promise >Promise.reject("1") : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >"1" : "1" >() => Promise.reject(1) : () => Promise >Promise.reject(1) : Promise ->Promise.reject : { (reason: any): Promise; (reason: any): Promise; } +>Promise.reject : (reason?: any) => Promise >Promise : PromiseConstructor ->reject : { (reason: any): Promise; (reason: any): Promise; } +>reject : (reason?: any) => Promise >1 : 1 From d1fde3786c4a1509b5172540bbaac02c05c22387 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 17 Apr 2018 14:07:59 -0700 Subject: [PATCH 25/62] Symbol kind for a method on a mapped type should still be 'method' (#23478) --- src/services/symbolDisplay.ts | 9 +++++++++ .../{server => }/quickInfoMappedSpreadTypes.ts | 2 +- tests/cases/fourslash/quickInfoMappedType.ts | 11 +++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) rename tests/cases/fourslash/{server => }/quickInfoMappedSpreadTypes.ts (89%) create mode 100644 tests/cases/fourslash/quickInfoMappedType.ts diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 7431393df87..f79c048efad 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -26,6 +26,15 @@ namespace ts.SymbolDisplay { } function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker: TypeChecker, symbol: Symbol, location: Node): ScriptElementKind { + const roots = typeChecker.getRootSymbols(symbol); + // If this is a method from a mapped type, leave as a method so long as it still has a call signature. + if (roots.length === 1 + && first(roots).flags & SymbolFlags.Method + // Ensure the mapped version is still a method, as opposed to `{ [K in keyof I]: number }`. + && typeChecker.getTypeOfSymbolAtLocation(symbol, location).getNonNullableType().getCallSignatures().length !== 0) { + return ScriptElementKind.memberFunctionElement; + } + if (typeChecker.isUndefinedSymbol(symbol)) { return ScriptElementKind.variableElement; } diff --git a/tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts b/tests/cases/fourslash/quickInfoMappedSpreadTypes.ts similarity index 89% rename from tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts rename to tests/cases/fourslash/quickInfoMappedSpreadTypes.ts index 2a0c1668763..c1e34f49bfc 100644 --- a/tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts +++ b/tests/cases/fourslash/quickInfoMappedSpreadTypes.ts @@ -1,4 +1,4 @@ -/// +/// ////interface Foo { //// /** Doc */ diff --git a/tests/cases/fourslash/quickInfoMappedType.ts b/tests/cases/fourslash/quickInfoMappedType.ts new file mode 100644 index 00000000000..c4afb444155 --- /dev/null +++ b/tests/cases/fourslash/quickInfoMappedType.ts @@ -0,0 +1,11 @@ +/// + +////interface I { m(): void; } +////declare const o: { [K in keyof I]: number }; +////o.m/*0*/; +//// +////declare const p: { [K in keyof I]: I[K] }; +////p.m/*1*/; + +verify.quickInfoAt("0", "(property) m: number"); +verify.quickInfoAt("1", "(method) m(): void"); From 4bfb1a3aa14972e536247feac316546d9965e790 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 17 Apr 2018 14:09:42 -0700 Subject: [PATCH 26/62] Avoid breaking change by introducing overloads for 'createTaggedTemplate'/'updateTaggedTemplate'. --- src/compiler/factory.ts | 27 ++++++++++++++++++++------- src/compiler/parser.ts | 1 - 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 7dd7216725a..e3191930c0e 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1032,19 +1032,32 @@ namespace ts { : node; } - export function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral) { + export function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + /** @internal */ + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral) { const node = createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizeForAccess(tag); - node.typeArguments = typeArguments; - node.template = template; + if (template) { + node.typeArguments = asNodeArray(typeArgumentsOrTemplate as ReadonlyArray); + node.template = template!; + } + else { + node.typeArguments = undefined; + node.template = typeArgumentsOrTemplate as TemplateLiteral; + } return node; } - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral) { + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral) { return node.tag !== tag - || node.typeArguments !== typeArguments - || node.template !== template - ? updateNode(createTaggedTemplate(tag, typeArguments, template), node) + || (template + ? node.typeArguments !== typeArgumentsOrTemplate || node.template !== template + : node.typeArguments !== undefined || node.template !== typeArgumentsOrTemplate) + ? updateNode(createTaggedTemplate(tag, typeArgumentsOrTemplate, template), node) : node; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f5dd8fa764d..4cf4c6e4c67 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4370,7 +4370,6 @@ namespace ts { return expression; } - } function isTemplateStartOfTaggedTemplate() { From 78e98c37841b17ce7d5c540050cc1e4925458d1c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 17 Apr 2018 14:15:36 -0700 Subject: [PATCH 27/62] Accepted baselines. --- tests/baselines/reference/api/tsserverlibrary.d.ts | 6 ++++-- tests/baselines/reference/api/typescript.d.ts | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a250dcf6961..06ecede8c88 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3517,8 +3517,10 @@ declare namespace ts { function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; - function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 4e15b26a13d..9d99813cfe1 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3517,8 +3517,10 @@ declare namespace ts { function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; - function createTaggedTemplate(tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; From d64f2483e4c8838ff7bc46fa106c69a05901769d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 17 Apr 2018 14:17:15 -0700 Subject: [PATCH 28/62] Update to respond to PR feedback --- src/compiler/core.ts | 2 +- src/compiler/resolutionCache.ts | 20 +++-- src/server/project.ts | 82 ++++++++----------- src/server/scriptInfo.ts | 10 +-- .../reference/api/tsserverlibrary.d.ts | 8 +- 5 files changed, 57 insertions(+), 65 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index b427c689c96..0e53ae2946d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2988,7 +2988,7 @@ namespace ts { /** Remove the *first* occurrence of `item` from the array. */ export function unorderedRemoveItem(array: T[], item: T) { - unorderedRemoveFirstItemWhere(array, element => element === item); + return unorderedRemoveFirstItemWhere(array, element => element === item); } /** Remove the *first* element satisfying `predicate`. */ diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 2cd39068de1..35e056546c0 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -10,7 +10,7 @@ namespace ts { invalidateResolutionOfFile(filePath: Path): void; removeResolutionsOfFile(filePath: Path): void; - setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map): void; + setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map>): void; createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution; startCachingPerDirectoryResolution(): void; @@ -75,7 +75,7 @@ namespace ts { export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string, logChangesWhenResolvingModule: boolean): ResolutionCache { let filesWithChangedSetOfUnresolvedImports: Path[] | undefined; let filesWithInvalidatedResolutions: Map | undefined; - let filesWithInvalidatedNonRelativeUnresolvedImports: Map | undefined; + let filesWithInvalidatedNonRelativeUnresolvedImports: Map> | undefined; let allFilesHaveInvalidatedResolution = false; const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory()); @@ -168,6 +168,16 @@ namespace ts { return collected; } + function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path) { + if (!filesWithInvalidatedNonRelativeUnresolvedImports) { + return false; + } + + // Invalidated if file has unresolved imports + const value = filesWithInvalidatedNonRelativeUnresolvedImports.get(path); + return value && !!value.length; + } + function createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution { if (allFilesHaveInvalidatedResolution || forceAllFilesAsInvalidated) { // Any file asked would have invalidated resolution @@ -177,7 +187,7 @@ namespace ts { const collected = filesWithInvalidatedResolutions; filesWithInvalidatedResolutions = undefined; return path => (collected && collected.has(path)) || - (filesWithInvalidatedNonRelativeUnresolvedImports && filesWithInvalidatedNonRelativeUnresolvedImports.has(path)); + isFileWithInvalidatedNonRelativeUnresolvedImports(path); } function clearPerDirectoryResolutions() { @@ -242,7 +252,7 @@ namespace ts { const resolvedModules: R[] = []; const compilerOptions = resolutionHost.getCompilationSettings(); - const hasInvalidatedNonRelativeUnresolvedImport = logChanges && filesWithInvalidatedNonRelativeUnresolvedImports && filesWithInvalidatedNonRelativeUnresolvedImports.has(path); + const hasInvalidatedNonRelativeUnresolvedImport = logChanges && isFileWithInvalidatedNonRelativeUnresolvedImports(path); const seenNamesInFile = createMap(); for (const name of names) { let resolution = resolutionsInFile.get(name); @@ -584,7 +594,7 @@ namespace ts { ); } - function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: Map) { + function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: Map>) { Debug.assert(filesWithInvalidatedNonRelativeUnresolvedImports === filesMap || filesWithInvalidatedNonRelativeUnresolvedImports === undefined); filesWithInvalidatedNonRelativeUnresolvedImports = filesMap; } diff --git a/src/server/project.ts b/src/server/project.ts index 67469cc69d8..653f2943d0a 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -96,15 +96,10 @@ namespace ts.server { */ cachedUnresolvedImportsPerFile = createMap>(); - /** - * This is the set that has entry to true if file doesnt contain any unresolved import - */ - private filesWithNoUnresolvedImports = createMap(); - /*@internal*/ lastCachedUnresolvedImportsList: SortedReadonlyArray; /*@internal*/ - hasMoreOrLessScriptInfos = false; + private hasMoreOrLessFiles = false; private lastFileExceededProgramSize: string | undefined; @@ -136,10 +131,10 @@ namespace ts.server { */ private lastReportedVersion = 0; /** - * Current project structure version. + * Current project's program version. (incremented everytime new program is created that is not complete reuse from the old one) * This property is changed in 'updateGraph' based on the set of files in program */ - private projectStructureVersion = 0; + private projectProgramVersion = 0; /** * Current version of the project state. It is changed when: * - new root file was added/removed @@ -566,7 +561,6 @@ namespace ts.server { this.resolutionCache.clear(); this.resolutionCache = undefined; this.cachedUnresolvedImportsPerFile = undefined; - this.filesWithNoUnresolvedImports = undefined; this.directoryStructureHost = undefined; // Clean up file watchers waiting for missing files @@ -727,7 +721,6 @@ namespace ts.server { else { this.resolutionCache.invalidateResolutionOfFile(info.path); } - this.filesWithNoUnresolvedImports.delete(info.path); this.cachedUnresolvedImportsPerFile.delete(info.path); if (detachFromProject) { @@ -749,19 +742,11 @@ namespace ts.server { } /* @internal */ - private extractUnresolvedImportsFromSourceFile(file: SourceFile, result: string[] | undefined, ambientModules: string[]): string[] | undefined { - // No unresolve imports in this file - if (this.filesWithNoUnresolvedImports.has(file.path)) { - return result; - } - + private extractUnresolvedImportsFromSourceFile(file: SourceFile, ambientModules: string[]): ReadonlyArray { const cached = this.cachedUnresolvedImportsPerFile.get(file.path); if (cached) { - // found cached result - use it and return - for (const f of cached) { - (result || (result = [])).push(f); - } - return result; + // found cached result, return + return cached; } let unresolvedImports: string[] | undefined; if (file.resolvedModules) { @@ -779,23 +764,23 @@ namespace ts.server { trimmed = trimmed.substr(0, i); } (unresolvedImports || (unresolvedImports = [])).push(trimmed); - (result || (result = [])).push(trimmed); } }); } - if (unresolvedImports) { - this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports); - } - else { - this.filesWithNoUnresolvedImports.set(file.path, true); - } - return result; + + this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports || emptyArray); + return unresolvedImports || emptyArray; function isAmbientlyDeclaredModule(name: string) { return ambientModules.some(m => m === name); } } + /* @internal */ + setHasMoreOrLessFiles() { + this.hasMoreOrLessFiles = true; + } + /** * Updates set of files that contribute to this project * @returns: true if set of files in the project stays the same and false - otherwise. @@ -803,16 +788,15 @@ namespace ts.server { updateGraph(): boolean { this.resolutionCache.startRecordingFilesWithChangedResolutions(); - const hasChanges = this.updateGraphWorker(); - const hasMoreOrLessScriptInfos = this.hasMoreOrLessScriptInfos; - this.hasMoreOrLessScriptInfos = false; + const hasNewProgram = this.updateGraphWorker(); + const hasMoreOrLessFiles = this.hasMoreOrLessFiles; + this.hasMoreOrLessFiles = false; const changedFiles: ReadonlyArray = this.resolutionCache.finishRecordingFilesWithChangedResolutions() || emptyArray; for (const file of changedFiles) { // delete cached information for changed files this.cachedUnresolvedImportsPerFile.delete(file); - this.filesWithNoUnresolvedImports.delete(file); } // update builder only if language service is enabled @@ -824,25 +808,28 @@ namespace ts.server { // 3. new files were added/removed, but compilation settings stays the same - collect unresolved imports for all new/modified files // (can reuse cached imports for files that were not changed) // 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch - if (hasChanges || changedFiles.length) { + if (hasNewProgram || changedFiles.length) { let result: string[] | undefined; const ambientModules = this.program.getTypeChecker().getAmbientModules().map(mod => stripQuotes(mod.getName())); for (const sourceFile of this.program.getSourceFiles()) { - result = this.extractUnresolvedImportsFromSourceFile(sourceFile, result, ambientModules); + const unResolved = this.extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules); + if (unResolved !== emptyArray) { + (result || (result = [])).push(...unResolved); + } } this.lastCachedUnresolvedImportsList = result ? toDeduplicatedSortedArray(result) : emptyArray; } - this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasMoreOrLessScriptInfos); + this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasMoreOrLessFiles); } else { this.lastCachedUnresolvedImportsList = undefined; } - if (hasChanges) { - this.projectStructureVersion++; + if (hasNewProgram) { + this.projectProgramVersion++; } - return !hasChanges; + return !hasNewProgram; } /*@internal*/ @@ -878,9 +865,9 @@ namespace ts.server { // bump up the version if // - oldProgram is not set - this is a first time updateGraph is called // - newProgram is different from the old program and structure of the old program was not reused. - const hasChanges = this.program && (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely))); + const hasNewProgram = this.program && (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely))); this.hasChangedAutomaticTypeDirectiveNames = false; - if (hasChanges) { + if (hasNewProgram) { if (oldProgram) { for (const f of oldProgram.getSourceFiles()) { if (this.program.getSourceFileByPath(f.path)) { @@ -918,8 +905,8 @@ namespace ts.server { removed => this.detachScriptInfoFromProject(removed) ); const elapsed = timestamp() - start; - this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasChanges} Elapsed: ${elapsed}ms`); - return hasChanges; + this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasNewProgram} Elapsed: ${elapsed}ms`); + return hasNewProgram; } private detachScriptInfoFromProject(uncheckedFileName: string) { @@ -993,7 +980,6 @@ namespace ts.server { if (changesAffectModuleResolution(oldOptions, compilerOptions)) { // reset cached unresolved imports if changes in compiler options affected module resolution this.cachedUnresolvedImportsPerFile.clear(); - this.filesWithNoUnresolvedImports.clear(); this.lastCachedUnresolvedImportsList = undefined; this.resolutionCache.clear(); } @@ -1007,7 +993,7 @@ namespace ts.server { const info: protocol.ProjectVersionInfo = { projectName: this.getProjectName(), - version: this.projectStructureVersion, + version: this.projectProgramVersion, isInferred: this.projectKind === ProjectKind.Inferred, options: this.getCompilationSettings(), languageServiceDisabled: !this.languageServiceEnabled, @@ -1018,7 +1004,7 @@ namespace ts.server { // check if requested version is the same that we have reported last time if (this.lastReportedFileNames && lastKnownVersion === this.lastReportedVersion) { // if current structure version is the same - return info without any changes - if (this.projectStructureVersion === this.lastReportedVersion && !updatedFileNames) { + if (this.projectProgramVersion === this.lastReportedVersion && !updatedFileNames) { return { info, projectErrors: this.getGlobalProjectErrors() }; } // compute and return the difference @@ -1041,7 +1027,7 @@ namespace ts.server { } }); this.lastReportedFileNames = currentFiles; - this.lastReportedVersion = this.projectStructureVersion; + this.lastReportedVersion = this.projectProgramVersion; return { info, changes: { added, removed, updated }, projectErrors: this.getGlobalProjectErrors() }; } else { @@ -1050,7 +1036,7 @@ namespace ts.server { const externalFiles = this.getExternalFiles().map(f => toNormalizedPath(f)); const allFiles = projectFileNames.concat(externalFiles); this.lastReportedFileNames = arrayToSet(allFiles); - this.lastReportedVersion = this.projectStructureVersion; + this.lastReportedVersion = this.projectProgramVersion; return { info, files: allFiles, projectErrors: this.getGlobalProjectErrors() }; } } diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 074fde298aa..cc4ebd519e5 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -304,7 +304,7 @@ namespace ts.server { const isNew = !this.isAttached(project); if (isNew) { this.containingProjects.push(project); - project.hasMoreOrLessScriptInfos = true; + project.setHasMoreOrLessFiles(); if (!project.getCompilerOptions().preserveSymlinks) { this.ensureRealPath(); } @@ -329,23 +329,23 @@ namespace ts.server { return; case 1: if (this.containingProjects[0] === project) { - project.hasMoreOrLessScriptInfos = true; + project.setHasMoreOrLessFiles(); this.containingProjects.pop(); } break; case 2: if (this.containingProjects[0] === project) { - project.hasMoreOrLessScriptInfos = true; + project.setHasMoreOrLessFiles(); this.containingProjects[0] = this.containingProjects.pop(); } else if (this.containingProjects[1] === project) { - project.hasMoreOrLessScriptInfos = true; + project.setHasMoreOrLessFiles(); this.containingProjects.pop(); } break; default: if (unorderedRemoveItem(this.containingProjects, project)) { - project.hasMoreOrLessScriptInfos = true; + project.setHasMoreOrLessFiles(); } break; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 53c23b1d382..a81f1c66c22 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7643,10 +7643,6 @@ declare namespace ts.server { private externalFiles; private missingFilesMap; private plugins; - /** - * This is the set that has entry to true if file doesnt contain any unresolved import - */ - private filesWithNoUnresolvedImports; private lastFileExceededProgramSize; protected languageService: LanguageService; languageServiceEnabled: boolean; @@ -7666,10 +7662,10 @@ declare namespace ts.server { */ private lastReportedVersion; /** - * Current project structure version. + * Current project's program version. (incremented everytime new program is created that is not complete reuse from the old one) * This property is changed in 'updateGraph' based on the set of files in program */ - private projectStructureVersion; + private projectProgramVersion; /** * Current version of the project state. It is changed when: * - new root file was added/removed From 391c0565d7c8138b2d9b3541faef648dfa9debd9 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 17 Apr 2018 17:19:42 -0400 Subject: [PATCH 29/62] Use ts-check instead of ts-node to avoid transpilation overhead on gulp startup (#23486) --- Gulpfile.ts => Gulpfile.js | 223 +++++++++++++++++++------------------ package.json | 1 - 2 files changed, 113 insertions(+), 111 deletions(-) rename Gulpfile.ts => Gulpfile.js (87%) diff --git a/Gulpfile.ts b/Gulpfile.js similarity index 87% rename from Gulpfile.ts rename to Gulpfile.js index 7f7e525564c..afa7e775dcd 100644 --- a/Gulpfile.ts +++ b/Gulpfile.js @@ -1,35 +1,27 @@ /// -import * as cp from "child_process"; -import * as path from "path"; -import * as fs from "fs"; -import child_process = require("child_process"); -import originalGulp = require("gulp"); -import helpMaker = require("gulp-help"); -import runSequence = require("run-sequence"); -import concat = require("gulp-concat"); -import clone = require("gulp-clone"); -import newer = require("gulp-newer"); -import tsc = require("gulp-typescript"); -declare module "gulp-typescript" { - interface Settings { - pretty?: boolean; - newLine?: string; - noImplicitThis?: boolean; - stripInternal?: boolean; - types?: string[]; - } -} -import * as insert from "gulp-insert"; -import * as sourcemaps from "gulp-sourcemaps"; -import Q = require("q"); -import del = require("del"); -import mkdirP = require("mkdirp"); -import minimist = require("minimist"); -import browserify = require("browserify"); -import through2 = require("through2"); -import merge2 = require("merge2"); -import * as os from "os"; -import fold = require("travis-fold"); +// @ts-check +const cp = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const child_process = require("child_process"); +const originalGulp = require("gulp"); +const helpMaker = require("gulp-help"); +const runSequence = require("run-sequence"); +const concat = require("gulp-concat"); +const clone = require("gulp-clone"); +const newer = require("gulp-newer"); +const tsc = require("gulp-typescript"); +const insert = require("gulp-insert"); +const sourcemaps = require("gulp-sourcemaps"); +const Q = require("q"); +const del = require("del"); +const mkdirP = require("mkdirp"); +const minimist = require("minimist"); +const browserify = require("browserify"); +const through2 = require("through2"); +const merge2 = require("merge2"); +const os = require("os"); +const fold = require("travis-fold"); const gulp = helpMaker(originalGulp); Error.stackTraceLimit = 1000; @@ -73,17 +65,26 @@ const cmdLineOptions = minimist(process.argv.slice(2), { }); const noop = () => {}; // tslint:disable-line no-empty -function exec(cmd: string, args: string[], complete: () => void = noop, error: (e: any, status: number) => void = noop) { +/** + * @param {string} cmd + * @param {string[]} args + * @param {() => void} complete + * @param {(e: *, status: number) => void} error + */ +function exec(cmd, args, complete = noop, error = noop) { console.log(`${cmd} ${args.join(" ")}`); // TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition const subshellFlag = isWin ? "/c" : "-c"; const command = isWin ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`]; - const ex = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true } as any); + const ex = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true }); ex.on("exit", (code) => code === 0 ? complete() : error(/*e*/ undefined, code)); ex.on("error", error); } -function possiblyQuote(cmd: string) { +/** + * @param {string} cmd + */ +function possiblyQuote(cmd) { return cmd.indexOf(" ") >= 0 ? `"${cmd}"` : cmd; } @@ -220,7 +221,12 @@ const configurePreleleaseTs = path.join(scriptsDirectory, "configurePrerelease.t const packageJson = "package.json"; const versionFile = path.join(compilerDirectory, "core.ts"); -function needsUpdate(source: string | string[], dest: string | string[]): boolean { +/** + * @param {string | string[]} source + * @param {string | string[]} dest + * @returns {boolean} + */ +function needsUpdate(source, dest) { if (typeof source === "string" && typeof dest === "string") { if (fs.existsSync(dest)) { const {mtime: outTime} = fs.statSync(dest); @@ -283,8 +289,13 @@ function needsUpdate(source: string | string[], dest: string | string[]): boolea return true; } -function getCompilerSettings(base: tsc.Settings, useBuiltCompiler?: boolean): tsc.Settings { - const copy: tsc.Settings = {}; +/** + * @param {tsc.Settings} base + * @param {boolean=} useBuiltCompiler + * @returns {tsc.Settings} + */ +function getCompilerSettings(base, useBuiltCompiler) { + const copy = /** @type {tsc.Settings} */ ({}); for (const key in base) { copy[key] = base[key]; } @@ -293,16 +304,17 @@ function getCompilerSettings(base: tsc.Settings, useBuiltCompiler?: boolean): ts } copy.newLine = "lf"; if (useBuiltCompiler === true) { - copy.typescript = require("./built/local/typescript.js"); + copy.typescript = /** @type {*} */ (require("./built/local/typescript.js")); } else if (useBuiltCompiler === false) { - copy.typescript = require("./lib/typescript.js"); + copy.typescript = /** @type {*} */ (require("./lib/typescript.js")); } return copy; } gulp.task(configurePreleleaseJs, /*help*/ false, [], () => { - const settings: tsc.Settings = { + /** @type {tsc.Settings} */ + const settings = { declaration: false, removeComments: true, noResolve: false, @@ -332,7 +344,8 @@ const importDefinitelyTypedTestsJs = path.join(importDefinitelyTypedTestsDirecto const importDefinitelyTypedTestsTs = path.join(importDefinitelyTypedTestsDirectory, "importDefinitelyTypedTests.ts"); gulp.task(importDefinitelyTypedTestsJs, /*help*/ false, [], () => { - const settings: tsc.Settings = getCompilerSettings({ + /** @type {tsc.Settings} */ + const settings = getCompilerSettings({ declaration: false, removeComments: true, noResolve: false, @@ -394,7 +407,8 @@ const generateLocalizedDiagnosticMessagesJs = path.join(scriptsDirectory, "gener const generateLocalizedDiagnosticMessagesTs = path.join(scriptsDirectory, "generateLocalizedDiagnosticMessages.ts"); gulp.task(generateLocalizedDiagnosticMessagesJs, /*help*/ false, [], () => { - const settings: tsc.Settings = getCompilerSettings({ + /** @type {tsc.Settings} */ + const settings = getCompilerSettings({ target: "es5", declaration: false, removeComments: true, @@ -425,8 +439,12 @@ const nodePackageFile = path.join(builtLocalDirectory, "typescript.js"); const nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts"); const nodeStandaloneDefinitionsFile = path.join(builtLocalDirectory, "typescript_standalone.d.ts"); -let copyrightContent: string; -function prependCopyright(outputCopyright: boolean = !useDebugMode) { +/** @type {string} */ +let copyrightContent; +/** + * @param {boolean} outputCopyright + */ +function prependCopyright(outputCopyright = !useDebugMode) { return insert.prepend(outputCopyright ? (copyrightContent || (copyrightContent = fs.readFileSync(copyright).toString())) : ""); } @@ -518,9 +536,10 @@ const tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverli gulp.task(tsserverLibraryFile, /*help*/ false, [servicesFile, typesMapJson], (done) => { const serverLibraryProject = tsc.createProject("src/server/tsconfig.library.json", getCompilerSettings({ removeComments: false }, /*useBuiltCompiler*/ true)); - const {js, dts}: { js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream } = serverLibraryProject.src() + /** @type {{ js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream }} */ + const {js, dts} = serverLibraryProject.src() .pipe(sourcemaps.init()) - .pipe(newer({ dest: tsserverLibraryFile, extra: ["src/compiler/**/*.ts", "src/services/**/*.ts"] })) + .pipe(newer(/** @type {*} */({ dest: tsserverLibraryFile, extra: ["src/compiler/**/*.ts", "src/services/**/*.ts"] }))) .pipe(serverLibraryProject()); return merge2([ @@ -555,7 +574,8 @@ const specWord = path.join(docDirectory, "TypeScript Language Specification.docx const specMd = path.join(docDirectory, "spec.md"); gulp.task(word2mdJs, /*help*/ false, [], () => { - const settings: tsc.Settings = getCompilerSettings({ + /** @type {tsc.Settings} */ + const settings = getCompilerSettings({ outFile: word2mdJs }, /*useBuiltCompiler*/ false); return gulp.src(word2mdTs) @@ -634,7 +654,8 @@ function deleteTemporaryProjectOutput() { return del(path.join(localBaseline, "projectOutput/")); } -let savedNodeEnv: string; +/** @type {string} */ +let savedNodeEnv; function setNodeEnvToDevelopment() { savedNodeEnv = process.env.NODE_ENV; process.env.NODE_ENV = "development"; @@ -644,7 +665,12 @@ function restoreSavedNodeEnv() { process.env.NODE_ENV = savedNodeEnv; } -function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: (e?: any) => void) { +/** + * @param {string} defaultReporter + * @param {boolean} runInParallel + * @param {(e?: any) => void} done + */ +function runConsoleTests(defaultReporter, runInParallel, done) { const lintFlag = cmdLineOptions.lint; cleanTestDirs((err) => { if (err) { console.error(err); failWithStatus(err, 1); } @@ -719,7 +745,11 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: } }); - function failWithStatus(err?: any, status?: number) { + /** + * @param {any=} err + * @param {number=} status + */ + function failWithStatus(err, status) { if (err || status) { process.exit(typeof status === "number" ? status : 2); } @@ -735,7 +765,11 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: } } - function finish(error?: any, errorStatus?: number) { + /** + * @param {any=} error + * @param {number=} errorStatus + */ + function finish(error, errorStatus) { restoreSavedNodeEnv(); deleteTestConfig().then(deleteTemporaryProjectOutput).then(() => { if (error !== undefined || errorStatus !== undefined) { @@ -765,7 +799,8 @@ gulp.task("runtests", const nodeServerOutFile = "tests/webTestServer.js"; const nodeServerInFile = "tests/webTestServer.ts"; gulp.task(nodeServerOutFile, /*help*/ false, [servicesFile], () => { - const settings: tsc.Settings = getCompilerSettings({ module: "commonjs" }, /*useBuiltCompiler*/ true); + /** @type {tsc.Settings} */ + const settings = getCompilerSettings({ module: "commonjs" }, /*useBuiltCompiler*/ true); return gulp.src(nodeServerInFile) .pipe(newer(nodeServerOutFile)) .pipe(sourcemaps.init()) @@ -774,16 +809,18 @@ gulp.task(nodeServerOutFile, /*help*/ false, [servicesFile], () => { .pipe(gulp.dest(path.dirname(nodeServerOutFile))); }); -import convertMap = require("convert-source-map"); -import sorcery = require("sorcery"); -import Vinyl = require("vinyl"); +const convertMap = require("convert-source-map"); +const sorcery = require("sorcery"); +const Vinyl = require("vinyl"); const bundlePath = path.resolve("built/local/bundle.js"); gulp.task("browserify", "Runs browserify on run.js to produce a file suitable for running tests in the browser", [servicesFile], (done) => { const testProject = tsc.createProject("src/harness/tsconfig.json", getCompilerSettings({ outFile: bundlePath, inlineSourceMap: true }, /*useBuiltCompiler*/ true)); - let originalMap: any; - let prebundledContent: string; + /** @type {*} */ + let originalMap; + /** @type {string} */ + let prebundledContent; browserify(testProject.src() .pipe(newer(bundlePath)) .pipe(sourcemaps.init()) @@ -847,8 +884,10 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo }); }); - -function cleanTestDirs(done: (e?: any) => void) { +/** + * @param {(e?: any) => void} done + */ +function cleanTestDirs(done) { // Clean the local baselines & Rwc baselines directories del([ localBaseline, @@ -864,8 +903,17 @@ function cleanTestDirs(done: (e?: any) => void) { }); } -// used to pass data from jake command line directly to run.js -function writeTestConfigFile(tests: string, runners: string, light: boolean, taskConfigsFolder?: string, workerCount?: number, stackTraceLimit?: string, timeout?: number) { +/** + * used to pass data from jake command line directly to run.js + * @param {string} tests + * @param {string} runners + * @param {boolean} light + * @param {string=} taskConfigsFolder + * @param {number=} workerCount + * @param {string=} stackTraceLimit + * @param {number=} timeout + */ +function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, timeout) { const testConfigContents = JSON.stringify({ test: tests ? [tests] : undefined, runner: runners ? runners.split(",") : undefined, @@ -966,7 +1014,7 @@ gulp.task("baseline-accept-test262", "Makes the most recent test262 test results const webhostPath = "tests/webhost/webtsc.ts"; const webhostJsPath = "tests/webhost/webtsc.js"; gulp.task(webhostJsPath, /*help*/ false, [servicesFile], () => { - const settings: tsc.Settings = getCompilerSettings({ + const settings = getCompilerSettings({ outFile: webhostJsPath }, /*useBuiltCompiler*/ true); return gulp.src(webhostPath) @@ -986,7 +1034,7 @@ gulp.task("webhost", "Builds the tsc web host", [webhostJsPath], () => { const perftscPath = "tests/perftsc.ts"; const perftscJsPath = "built/local/perftsc.js"; gulp.task(perftscJsPath, /*help*/ false, [servicesFile], () => { - const settings: tsc.Settings = getCompilerSettings({ + const settings = getCompilerSettings({ outFile: perftscJsPath }, /*useBuiltCompiler*/ true); return gulp.src(perftscPath) @@ -1017,7 +1065,7 @@ gulp.task(loggedIOJsPath, /*help*/ false, [], (done) => { const instrumenterPath = path.join(harnessDirectory, "instrumenter.ts"); const instrumenterJsPath = path.join(builtLocalDirectory, "instrumenter.js"); gulp.task(instrumenterJsPath, /*help*/ false, [servicesFile], () => { - const settings: tsc.Settings = getCompilerSettings({ + const settings = getCompilerSettings({ module: "commonjs", target: "es5", lib: [ @@ -1044,7 +1092,7 @@ gulp.task("update-sublime", "Updates the sublime plugin's tsserver", ["local", s }); gulp.task("build-rules", "Compiles tslint rules to js", () => { - const settings: tsc.Settings = getCompilerSettings({ module: "commonjs", lib: ["es6"] }, /*useBuiltCompiler*/ false); + const settings = getCompilerSettings({ module: "commonjs", lib: ["es6"] }, /*useBuiltCompiler*/ false); const dest = path.join(builtLocalDirectory, "tslint"); return gulp.src("scripts/tslint/**/*.ts") .pipe(newer({ @@ -1057,51 +1105,6 @@ gulp.task("build-rules", "Compiles tslint rules to js", () => { .pipe(gulp.dest(dest)); }); -const lintTargets = [ - "Gulpfile.ts", - "src/compiler/**/*.ts", - "src/harness/**/*.ts", - "!src/harness/unittests/services/formatting/**/*.ts", - "src/server/**/*.ts", - "scripts/tslint/**/*.ts", - "src/services/**/*.ts", - "tests/*.ts", "tests/webhost/*.ts" // Note: does *not* descend recursively -]; - -function sendNextFile(files: {path: string}[], child: cp.ChildProcess, callback: (failures: number) => void, failures: number) { - const file = files.pop(); - if (file) { - console.log(`Linting '${file.path}'.`); - child.send({ kind: "file", name: file.path }); - } - else { - child.send({ kind: "close" }); - callback(failures); - } -} - -function spawnLintWorker(files: {path: string}[], callback: (failures: number) => void) { - const child = cp.fork("./scripts/parallel-lint"); - let failures = 0; - child.on("message", data => { - switch (data.kind) { - case "result": - if (data.failures > 0) { - failures += data.failures; - console.log(data.output); - } - sendNextFile(files, child, callback, failures); - break; - case "error": - console.error(data.error); - failures++; - sendNextFile(files, child, callback, failures); - break; - } - }); - sendNextFile(files, child, callback, failures); -} - gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex", ["build-rules"], () => { if (fold.isTravis()) console.log(fold.start("lint")); for (const project of ["scripts/tslint/tsconfig.json", "src/tsconfig-base.json"]) { diff --git a/package.json b/package.json index 5837f72317f..71b5ed71029 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,6 @@ "source-map-support": "latest", "through2": "latest", "travis-fold": "latest", - "ts-node": "latest", "tslint": "latest", "vinyl": "latest", "chalk": "latest", From db9620d8f01f1047fe93102bf37527ff30b43c83 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 17 Apr 2018 12:18:49 -0700 Subject: [PATCH 30/62] Use watch recursive directories instead of watchFile for node_modules and bower components --- .../unittests/tsserverProjectSystem.ts | 8 +- src/harness/unittests/typingsInstaller.ts | 30 +++- src/harness/virtualFileSystemWithWatch.ts | 10 +- src/server/types.ts | 2 + .../typingsInstaller/typingsInstaller.ts | 139 ++++++++++++++---- 5 files changed, 151 insertions(+), 38 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 10912b4fb87..a35f797eaa1 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -13,7 +13,9 @@ namespace ts.projectSystem { export import checkArray = TestFSWithWatch.checkArray; export import libFile = TestFSWithWatch.libFile; export import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles; - import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories; + export import checkWatchedFilesDetailed = TestFSWithWatch.checkWatchedFilesDetailed; + export import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories; + export import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed; import safeList = TestFSWithWatch.safeList; export const customTypesMap = { @@ -7821,8 +7823,8 @@ namespace ts.projectSystem { checkWatchedDirectories(host, emptyArray, /*recursive*/ true); - TestFSWithWatch.checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedWatchedFiles); - TestFSWithWatch.checkMultiMapKeyCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories); + checkWatchedFilesDetailed(host, expectedWatchedFiles); + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectories, /*recursive*/ false); checkProjectActualFiles(project, fileNames); } } diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index b6d5a20ef9a..a8c7d4895d1 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -141,7 +141,19 @@ namespace ts.projectSystem { checkNumberOfProjects(projectService, { configuredProjects: 1 }); const p = configuredProjectAt(projectService, 0); checkProjectActualFiles(p, [file1.path, tsconfig.path]); - checkWatchedFiles(host, [tsconfig.path, libFile.path, packageJson.path, "/a/b/bower_components", "/a/b/node_modules"]); + + const expectedWatchedFiles = createMap(); + expectedWatchedFiles.set(tsconfig.path, 1); // tsserver + expectedWatchedFiles.set(libFile.path, 1); // tsserver + expectedWatchedFiles.set(packageJson.path, 1); // typing installer + checkWatchedFilesDetailed(host, expectedWatchedFiles); + + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + + const expectedWatchedDirectoriesRecursive = createMap(); + expectedWatchedDirectoriesRecursive.set("/a/b", 2); // TypingInstaller and wild card + expectedWatchedDirectoriesRecursive.set("/a/b/node_modules/@types", 1); // type root watch + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesRecursive, /*recursive*/ true); installer.installAll(/*expectedCount*/ 1); @@ -149,7 +161,9 @@ namespace ts.projectSystem { host.checkTimeoutQueueLengthAndRun(2); checkProjectActualFiles(p, [file1.path, jquery.path, tsconfig.path]); // should not watch jquery - checkWatchedFiles(host, [tsconfig.path, libFile.path, packageJson.path, "/a/b/bower_components", "/a/b/node_modules"]); + checkWatchedFilesDetailed(host, expectedWatchedFiles); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesRecursive, /*recursive*/ true); }); it("inferred project (typings installed)", () => { @@ -827,7 +841,17 @@ namespace ts.projectSystem { checkNumberOfProjects(projectService, { configuredProjects: 1 }); const p = configuredProjectAt(projectService, 0); checkProjectActualFiles(p, [app.path, jsconfig.path]); - checkWatchedFiles(host, [jsconfig.path, "/bower_components", "/node_modules", libFile.path]); + + const watchedFilesExpected = createMap(); + watchedFilesExpected.set(jsconfig.path, 1); // project files + watchedFilesExpected.set(libFile.path, 1); // project files + checkWatchedFilesDetailed(host, watchedFilesExpected); + + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + + const watchedRecursiveDirectoriesExpected = createMap(); + watchedRecursiveDirectoriesExpected.set("/", 2); // wild card + type installer + checkWatchedDirectoriesDetailed(host, watchedRecursiveDirectoriesExpected, /*recursive*/ true); installer.installAll(/*expectedCount*/ 1); diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 71b7da2ed14..3756f435d43 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -179,10 +179,18 @@ interface Array {}` checkMapKeys("watchedFiles", host.watchedFiles, expectedFiles); } - export function checkWatchedDirectories(host: TestServerHost, expectedDirectories: string[], recursive = false) { + export function checkWatchedFilesDetailed(host: TestServerHost, expectedFiles: Map) { + checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedFiles); + } + + export function checkWatchedDirectories(host: TestServerHost, expectedDirectories: string[], recursive: boolean) { checkMapKeys(`watchedDirectories${recursive ? " recursive" : ""}`, recursive ? host.watchedDirectoriesRecursive : host.watchedDirectories, expectedDirectories); } + export function checkWatchedDirectoriesDetailed(host: TestServerHost, expectedDirectories: Map, recursive: boolean) { + checkMultiMapKeyCount(`watchedDirectories${recursive ? " recursive" : ""}`, recursive ? host.watchedDirectoriesRecursive : host.watchedDirectories, expectedDirectories); + } + export function checkOutputContains(host: TestServerHost, expected: ReadonlyArray) { const mapExpected = arrayToSet(expected); const mapSeen = createMap(); diff --git a/src/server/types.ts b/src/server/types.ts index d4ddd81c53e..184a121522e 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -119,8 +119,10 @@ declare namespace ts.server { /* @internal */ export interface InstallTypingHost extends JsTyping.TypingResolutionHost { + useCaseSensitiveFileNames: boolean; writeFile(path: string, content: string): void; createDirectory(path: string): void; watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; + watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; } } diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index f79564f6f98..0bff32958be 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -64,6 +64,15 @@ namespace ts.server.typingsInstaller { onRequestCompleted: RequestCompletedAction; } + function isPackageOrBowerJson(fileName: string) { + const base = getBaseFileName(fileName); + return base === "package.json" || base === "bower.json"; + } + + function isInNodeModulesOrBowerComponents(f: string) { + return stringContains(f, "/node_modules/") || stringContains(f, "/bower_components/"); + } + type ProjectWatchers = Map & { isInvoked?: boolean; }; export abstract class TypingsInstaller { @@ -73,6 +82,7 @@ namespace ts.server.typingsInstaller { private readonly projectWatchers = createMap(); private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; + private readonly toCanonicalFileName: GetCanonicalFileName; private installRunCount = 1; private inFlightRequestCount = 0; @@ -86,6 +96,7 @@ namespace ts.server.typingsInstaller { private readonly typesMapLocation: Path, private readonly throttleLimit: number, protected readonly log = nullLog) { + this.toCanonicalFileName = createGetCanonicalFileName(installTypingHost.useCaseSensitiveFileNames); if (this.log.isEnabled()) { this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}', types map path ${typesMapLocation}`); } @@ -147,7 +158,7 @@ namespace ts.server.typingsInstaller { } // start watching files - this.watchFiles(req.projectName, discoverTypingsResult.filesToWatch); + this.watchFiles(req.projectName, discoverTypingsResult.filesToWatch, req.projectRootPath); // install typings if (discoverTypingsResult.newTypingNames.length) { @@ -367,7 +378,7 @@ namespace ts.server.typingsInstaller { } } - private watchFiles(projectName: string, files: string[]) { + private watchFiles(projectName: string, files: string[], projectRootPath: Path) { if (!files.length) { // shut down existing watchers this.closeWatchers(projectName); @@ -375,43 +386,109 @@ namespace ts.server.typingsInstaller { } let watchers = this.projectWatchers.get(projectName); + const toRemove = createMap(); if (!watchers) { watchers = createMap(); this.projectWatchers.set(projectName, watchers); } + else { + copyEntries(watchers, toRemove); + } - watchers.isInvoked = false; // handler should be invoked once for the entire set of files since it will trigger full rediscovery of typings + watchers.isInvoked = false; + const isLoggingEnabled = this.log.isEnabled(); - mutateMap( - watchers, - arrayToSet(files), - { - // Watch the missing files - createNewValue: file => { - if (isLoggingEnabled) { - this.log.writeLine(`FileWatcher:: Added:: WatchInfo: ${file}`); - } - const watcher = this.installTypingHost.watchFile(file, (f, eventKind) => { - if (isLoggingEnabled) { - this.log.writeLine(`FileWatcher:: Triggered with ${f} eventKind: ${FileWatcherEventKind[eventKind]}:: WatchInfo: ${file}:: handler is already invoked '${watchers.isInvoked}'`); - } - if (!watchers.isInvoked) { - watchers.isInvoked = true; - this.sendResponse({ projectName, kind: ActionInvalidate }); - } - }, /*pollingInterval*/ 2000); - return isLoggingEnabled ? { - close: () => { - this.log.writeLine(`FileWatcher:: Closed:: WatchInfo: ${file}`); - } - } : watcher; - }, - // Files that are no longer missing (e.g. because they are no longer required) - // should no longer be watched. - onDeleteValue: closeFileWatcher + const createProjectWatcher = (path: string, createWatch: (path: string) => FileWatcher) => { + toRemove.delete(path); + if (watchers.has(path)) { + return; } - ); + + watchers.set(path, createWatch(path)); + }; + const createProjectFileWatcher = (file: string): FileWatcher => { + if (isLoggingEnabled) { + this.log.writeLine(`FileWatcher:: Added:: WatchInfo: ${file}`); + } + const watcher = this.installTypingHost.watchFile(file, (f, eventKind) => { + if (isLoggingEnabled) { + this.log.writeLine(`FileWatcher:: Triggered with ${f} eventKind: ${FileWatcherEventKind[eventKind]}:: WatchInfo: ${file}:: handler is already invoked '${watchers.isInvoked}'`); + } + if (!watchers.isInvoked) { + watchers.isInvoked = true; + this.sendResponse({ projectName, kind: ActionInvalidate }); + } + }, /*pollingInterval*/ 2000); + + return isLoggingEnabled ? { + close: () => { + this.log.writeLine(`FileWatcher:: Closed:: WatchInfo: ${file}`); + watcher.close(); + } + } : watcher; + }; + const createProjectDirectoryWatcher = (dir: string): FileWatcher => { + if (isLoggingEnabled) { + this.log.writeLine(`DirectoryWatcher:: Added:: WatchInfo: ${dir} recursive`); + } + const watcher = this.installTypingHost.watchDirectory(dir, f => { + if (isLoggingEnabled) { + this.log.writeLine(`DirectoryWatcher:: Triggered with ${f} :: WatchInfo: ${dir} recursive :: handler is already invoked '${watchers.isInvoked}'`); + } + if (watchers.isInvoked) { + return; + } + f = this.toCanonicalFileName(f); + if (isPackageOrBowerJson(f) && f !== this.toCanonicalFileName(combinePaths(this.globalCachePath, "package.json"))) { + watchers.isInvoked = true; + this.sendResponse({ projectName, kind: ActionInvalidate }); + } + }, /*recursive*/ true); + + return isLoggingEnabled ? { + close: () => { + this.log.writeLine(`DirectoryWatcher:: Closed:: WatchInfo: ${dir} recursive`); + watcher.close(); + } + } : watcher; + }; + + // Create watches from list of files + for (const file of files) { + const filePath = this.toCanonicalFileName(file); + if (isPackageOrBowerJson(filePath)) { + // package.json or bower.json exists, watch the file to detect changes and update typings + createProjectWatcher(filePath, createProjectFileWatcher); + continue; + } + + // path in projectRoot, watch project root + if (containsPath(projectRootPath, filePath, projectRootPath, !this.installTypingHost.useCaseSensitiveFileNames)) { + createProjectWatcher(projectRootPath, createProjectDirectoryWatcher); + continue; + } + + // path in global cache, watch global cache + if (containsPath(this.globalCachePath, filePath, projectRootPath, !this.installTypingHost.useCaseSensitiveFileNames)) { + createProjectWatcher(this.globalCachePath, createProjectDirectoryWatcher); + continue; + } + + // Get path without node_modules and bower_components + let pathToWatch = getDirectoryPath(filePath); + while (isInNodeModulesOrBowerComponents(pathToWatch)) { + pathToWatch = getDirectoryPath(pathToWatch); + } + + createProjectWatcher(pathToWatch, createProjectDirectoryWatcher); + } + + // Remove unused watches + toRemove.forEach((watch, path) => { + watch.close(); + watchers.delete(path); + }); } private createSetTypings(request: DiscoverTypings, typings: string[]): SetTypings { From f5101e21c36f19cbd30ae32b6945618a3e9dc98d Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 17 Apr 2018 15:01:36 -0700 Subject: [PATCH 31/62] Find-all-references: Don't crash on 'typeof import' (#23448) * Find-all-references: Don't crash on 'typeof import' * Move `| ImportTypeNode` out of `AnyImportOrReExport` --- src/compiler/types.ts | 3 ++- src/compiler/utilities.ts | 8 +++++++- src/services/importTracker.ts | 6 +++++- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + tests/cases/fourslash/findAllRefsTypeofImport.ts | 8 ++++++++ 6 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/findAllRefsTypeofImport.ts diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 63720d55900..d038d4281b0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3193,7 +3193,8 @@ namespace ts { export type AnyValidImportOrReExport = | (ImportDeclaration | ExportDeclaration) & { moduleSpecifier: StringLiteral } | ImportEqualsDeclaration & { moduleReference: ExternalModuleReference & { expression: StringLiteral } } - | RequireOrImportCall; + | RequireOrImportCall + | ImportTypeNode & { argument: LiteralType }; /* @internal */ export type RequireOrImportCall = CallExpression & { arguments: [StringLiteralLike] }; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f975e27dca3..e9d6f026b4e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1710,8 +1710,10 @@ namespace ts { return (node.parent as ExternalModuleReference).parent as AnyValidImportOrReExport; case SyntaxKind.CallExpression: return node.parent as AnyValidImportOrReExport; + case SyntaxKind.LiteralType: + return cast(node.parent.parent, isImportTypeNode) as ImportTypeNode & { argument: LiteralType }; default: - return Debug.fail(Debug.showSyntaxKind(node)); + return Debug.fail(Debug.showSyntaxKind(node.parent)); } } @@ -4926,6 +4928,10 @@ namespace ts { return node.kind === SyntaxKind.LiteralType; } + export function isImportTypeNode(node: Node): node is ImportTypeNode { + return node.kind === SyntaxKind.ImportType; + } + // Binding patterns export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 82f9fc00af6..80f0721e642 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -33,7 +33,7 @@ namespace ts.FindAllReferences { interface AmbientModuleDeclaration extends ModuleDeclaration { body?: ModuleBlock; } type SourceFileLike = SourceFile | AmbientModuleDeclaration; // Identifier for the case of `const x = require("y")`. - type Importer = AnyImportOrReExport | Identifier; + type Importer = AnyImportOrReExport | ImportTypeNode | Identifier; type ImporterOrCallExpression = Importer | CallExpression; /** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */ @@ -215,6 +215,10 @@ namespace ts.FindAllReferences { return; } + if (decl.kind === SyntaxKind.ImportType) { + return; + } + // Ignore if there's a grammar error if (decl.moduleSpecifier.kind !== SyntaxKind.StringLiteral) { return; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 04fabe6ff09..f5f60338aa9 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3169,6 +3169,7 @@ declare namespace ts { function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode; function isMappedTypeNode(node: Node): node is MappedTypeNode; function isLiteralTypeNode(node: Node): node is LiteralTypeNode; + function isImportTypeNode(node: Node): node is ImportTypeNode; function isObjectBindingPattern(node: Node): node is ObjectBindingPattern; function isArrayBindingPattern(node: Node): node is ArrayBindingPattern; function isBindingElement(node: Node): node is BindingElement; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 506aa6b15c6..b64ef40646c 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3169,6 +3169,7 @@ declare namespace ts { function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode; function isMappedTypeNode(node: Node): node is MappedTypeNode; function isLiteralTypeNode(node: Node): node is LiteralTypeNode; + function isImportTypeNode(node: Node): node is ImportTypeNode; function isObjectBindingPattern(node: Node): node is ObjectBindingPattern; function isArrayBindingPattern(node: Node): node is ArrayBindingPattern; function isBindingElement(node: Node): node is BindingElement; diff --git a/tests/cases/fourslash/findAllRefsTypeofImport.ts b/tests/cases/fourslash/findAllRefsTypeofImport.ts new file mode 100644 index 00000000000..77bd2d51a8c --- /dev/null +++ b/tests/cases/fourslash/findAllRefsTypeofImport.ts @@ -0,0 +1,8 @@ +/// + +// @Filename: /a.ts +////export const [|{| "isWriteAccess": true, "isDefinition": true |}x|] = 0; +////declare const a: typeof import("./a"); +////a.[|x|]; + +verify.singleReferenceGroup("const x: 0"); From e26745f129404109948f91d6803e92f5f14c24b6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 17 Apr 2018 15:20:48 -0700 Subject: [PATCH 32/62] Add axios' source to user tests (#23490) * Add axios' source to user tests We already have the npm-installed version in order to test their d.ts so that we don't break their users. * Just compile lib, plus fix some config lint --- .gitmodules | 5 +++ tests/baselines/reference/user/axios-src.log | 44 ++++++++++++++++++++ tests/cases/user/axios-src/axios-src | 1 + tests/cases/user/axios-src/test.json | 3 ++ tests/cases/user/axios-src/tsconfig.json | 14 +++++++ 5 files changed, 67 insertions(+) create mode 100644 tests/baselines/reference/user/axios-src.log create mode 160000 tests/cases/user/axios-src/axios-src create mode 100644 tests/cases/user/axios-src/test.json create mode 100644 tests/cases/user/axios-src/tsconfig.json diff --git a/.gitmodules b/.gitmodules index ccb2be81520..fdf474a693d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,8 @@ [submodule "tests/cases/user/puppeteer/puppeteer"] path = tests/cases/user/puppeteer/puppeteer url = https://github.com/GoogleChrome/puppeteer.git + ignore = all +[submodule "tests/cases/user/axios-src/axios-src"] + path = tests/cases/user/axios-src/axios-src + url = https://github.com/axios/axios.git + ignore = all diff --git a/tests/baselines/reference/user/axios-src.log b/tests/baselines/reference/user/axios-src.log new file mode 100644 index 00000000000..ad8bc285bbb --- /dev/null +++ b/tests/baselines/reference/user/axios-src.log @@ -0,0 +1,44 @@ +Exit Code: 1 +Standard output: +lib/adapters/http.js(12,19): error TS2307: Cannot find module './../../package.json'. +lib/adapters/http.js(83,22): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. + Type 'undefined' is not assignable to type 'string'. +lib/adapters/http.js(189,23): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string | undefined'. +lib/adapters/http.js(195,44): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string | undefined'. +lib/adapters/http.js(201,13): error TS2322: Type 'string' is not assignable to type 'Buffer'. +lib/adapters/http.js(213,40): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string | undefined'. +lib/adapters/http.js(237,42): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string | undefined'. +lib/adapters/xhr.js(29,16): error TS2339: Property 'XDomainRequest' does not exist on type 'Window'. +lib/adapters/xhr.js(31,28): error TS2339: Property 'XDomainRequest' does not exist on type 'Window'. +lib/adapters/xhr.js(80,7): error TS2322: Type 'null' is not assignable to type 'XMLHttpRequest'. +lib/adapters/xhr.js(92,7): error TS2322: Type 'null' is not assignable to type 'XMLHttpRequest'. +lib/adapters/xhr.js(99,51): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string | undefined'. +lib/adapters/xhr.js(102,7): error TS2322: Type 'null' is not assignable to type 'XMLHttpRequest'. +lib/adapters/xhr.js(111,7): error TS2322: Type 'null' is not assignable to type 'XMLHttpRequest'. +lib/adapters/xhr.js(181,9): error TS2322: Type 'null' is not assignable to type 'XMLHttpRequest'. +lib/axios.js(23,3): error TS2554: Expected 3 arguments, but got 2. +lib/axios.js(25,3): error TS2322: Type '(...args: any[]) => any' is not assignable to type 'Axios'. + Property 'defaults' is missing in type '(...args: any[]) => any'. +lib/axios.js(32,7): error TS2339: Property 'Axios' does not exist on type 'Axios'. +lib/axios.js(35,7): error TS2339: Property 'create' does not exist on type 'Axios'. +lib/axios.js(40,7): error TS2339: Property 'Cancel' does not exist on type 'Axios'. +lib/axios.js(41,7): error TS2339: Property 'CancelToken' does not exist on type 'Axios'. +lib/axios.js(42,7): error TS2339: Property 'isCancel' does not exist on type 'Axios'. +lib/axios.js(45,7): error TS2339: Property 'all' does not exist on type 'Axios'. +lib/axios.js(48,7): error TS2339: Property 'spread' does not exist on type 'Axios'. +lib/cancel/CancelToken.js(37,12): error TS2339: Property 'reason' does not exist on type 'CancelToken'. +lib/cancel/CancelToken.js(38,16): error TS2339: Property 'reason' does not exist on type 'CancelToken'. +lib/core/enhanceError.js(14,9): error TS2339: Property 'config' does not exist on type 'Error'. +lib/core/enhanceError.js(16,11): error TS2339: Property 'code' does not exist on type 'Error'. +lib/core/enhanceError.js(18,9): error TS2339: Property 'request' does not exist on type 'Error'. +lib/core/enhanceError.js(19,9): error TS2339: Property 'response' does not exist on type 'Error'. +lib/core/settle.js(21,7): error TS2345: Argument of type 'null' is not assignable to parameter of type 'string | undefined'. +lib/helpers/btoa.js(11,13): error TS2339: Property 'code' does not exist on type 'Error'. +lib/helpers/btoa.js(31,13): error TS2532: Object is possibly 'undefined'. +lib/helpers/cookies.js(16,56): error TS2551: Property 'toGMTString' does not exist on type 'Date'. Did you mean 'toUTCString'? +lib/utils.js(244,20): error TS8029: JSDoc '@param' tag has name 'obj1', but there is no parameter with that name. It would match 'arguments' if it had an array type. +lib/utils.js(268,20): error TS8029: JSDoc '@param' tag has name 'obj1', but there is no parameter with that name. It would match 'arguments' if it had an array type. + + + +Standard error: diff --git a/tests/cases/user/axios-src/axios-src b/tests/cases/user/axios-src/axios-src new file mode 160000 index 00000000000..0b3db5d87a6 --- /dev/null +++ b/tests/cases/user/axios-src/axios-src @@ -0,0 +1 @@ +Subproject commit 0b3db5d87a60a1ad8b0dce9669dbc10483ec33da diff --git a/tests/cases/user/axios-src/test.json b/tests/cases/user/axios-src/test.json new file mode 100644 index 00000000000..b6495a1b80b --- /dev/null +++ b/tests/cases/user/axios-src/test.json @@ -0,0 +1,3 @@ +{ + "types": ["node"] +} diff --git a/tests/cases/user/axios-src/tsconfig.json b/tests/cases/user/axios-src/tsconfig.json new file mode 100644 index 00000000000..ef3f63dc126 --- /dev/null +++ b/tests/cases/user/axios-src/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "noImplicitAny": false, + "noImplicitThis": false, + "maxNodeModuleJsDepth": 0, + "strict": true, + "noEmit": true, + "allowJs": true, + "checkJs": true, + "types": ["node"], + "lib": ["esnext", "dom"], + }, + "include": ["axios-src/lib"] +} From 6953fa17328809c0b4db08e9a91adb2196957496 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 17 Apr 2018 17:06:50 -0700 Subject: [PATCH 33/62] flags--; --- src/compiler/commandLineParser.ts | 8 -------- src/compiler/tsc.ts | 4 ++-- src/compiler/types.ts | 8 -------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 2de922b4159..470bd111492 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -56,14 +56,6 @@ namespace ts { category: Diagnostics.Command_line_Options, description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental }, - { - name: "diagnosticStyle", - type: createMapFromTemplate({ - auto: DiagnosticStyle.Auto, - pretty: DiagnosticStyle.Pretty, - simple: DiagnosticStyle.Simple, - }), - }, { name: "preserveWatchOutput", type: "boolean", diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 56c3c323f30..b2bffd83ca7 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -25,10 +25,10 @@ namespace ts { } function shouldBePretty(options: CompilerOptions) { - if ((typeof options.pretty === "undefined" && typeof options.diagnosticStyle === "undefined") || options.diagnosticStyle === DiagnosticStyle.Auto) { + if ((typeof options.pretty === "undefined")) { return !!sys.writeOutputIsTty && sys.writeOutputIsTty(); } - return options.diagnosticStyle === DiagnosticStyle.Pretty || options.pretty; + return options.pretty; } function padLeft(s: string, length: number) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 802c175b573..8962a7d0280 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4194,7 +4194,6 @@ namespace ts { /* @internal */ preserveWatchOutput?: boolean; project?: string; /* @internal */ pretty?: boolean; - /* @internal */ diagnosticStyle?: DiagnosticStyle; reactNamespace?: string; jsxFactory?: string; removeComments?: boolean; @@ -4292,13 +4291,6 @@ namespace ts { JSX, } - /* @internal */ - export const enum DiagnosticStyle { - Auto, - Pretty, - Simple, - } - /** Either a parsed command line or a parsed tsconfig.json */ export interface ParsedCommandLine { options: CompilerOptions; From 563660a83a35b460156d53e455eaf1c7fab42523 Mon Sep 17 00:00:00 2001 From: falsandtru Date: Wed, 18 Apr 2018 11:22:22 +0900 Subject: [PATCH 34/62] Revert the change of PromiseLikeConstructor --- src/lib/es5.d.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index c213677feac..1f352cd6f39 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1273,9 +1273,7 @@ declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) declare type MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void; declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void; -interface PromiseConstructorLike { - new (executor: (resolve: [T] extends [void] ? (value?: T | PromiseLike) => void : (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): PromiseLike; -} +declare type PromiseConstructorLike = new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void) => PromiseLike; interface PromiseLike { /** From 26c836b12a56063ddde7586cdf37127ba174a7f5 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 17 Apr 2018 19:44:52 -0700 Subject: [PATCH 35/62] Propagage reportsUnnecessary in convertToDiagnosticsWithLinePosition --- src/server/session.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/session.ts b/src/server/session.ts index 1076d17e11f..27044ec369d 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -634,7 +634,8 @@ namespace ts.server { code: d.code, source: d.source, startLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start), - endLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start + d.length) + endLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start + d.length), + reportsUnnecessary: d.reportsUnnecessary }); } From 4318f0d9a0bd17cf4a7c502c3fe57c8538efa5c0 Mon Sep 17 00:00:00 2001 From: falsandtru Date: Wed, 18 Apr 2018 11:45:01 +0900 Subject: [PATCH 36/62] Improve PromiseConstructor --- src/lib/es2015.promise.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/es2015.promise.d.ts b/src/lib/es2015.promise.d.ts index af43abe63d6..65986e85baf 100644 --- a/src/lib/es2015.promise.d.ts +++ b/src/lib/es2015.promise.d.ts @@ -10,7 +10,7 @@ interface PromiseConstructor { * a resolve callback used resolve the promise with a value or the result of another promise, * and a reject callback used to reject the promise with a provided reason or error. */ - new (executor: (resolve: [T] extends [void] ? (value?: T | PromiseLike) => void : (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + new (executor: (resolve: [void] extends [T] ? (value?: T | PromiseLike) => void : (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; /** * Creates a Promise that is resolved with an array of results when all of the provided Promises From 81b347d61da5ba100bd09fef6d863520e6c48a21 Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 18 Apr 2018 04:10:18 +0000 Subject: [PATCH 37/62] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 58326d7ccb6..b2ffdf585e0 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3894,6 +3894,15 @@ + + + + + + + + + @@ -6003,6 +6012,9 @@ + + + From afde2b5bf3d90526493dbb2ef40553be0ca48d17 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 18 Apr 2018 07:55:57 -0700 Subject: [PATCH 38/62] MissingDeclaration is only ever a Statement (#23485) --- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 9 +++------ tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d038d4281b0..19034c3469e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1892,7 +1892,7 @@ namespace ts { kind: SyntaxKind.DebuggerStatement; } - export interface MissingDeclaration extends DeclarationStatement, ClassElement, ObjectLiteralElement, TypeElement { + export interface MissingDeclaration extends DeclarationStatement { kind: SyntaxKind.MissingDeclaration; name?: Identifier; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e9d6f026b4e..3fe255fb612 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5612,8 +5612,7 @@ namespace ts { || kind === SyntaxKind.GetAccessor || kind === SyntaxKind.SetAccessor || kind === SyntaxKind.IndexSignature - || kind === SyntaxKind.SemicolonClassElement - || kind === SyntaxKind.MissingDeclaration; + || kind === SyntaxKind.SemicolonClassElement; } export function isClassLike(node: Node): node is ClassLikeDeclaration { @@ -5644,8 +5643,7 @@ namespace ts { || kind === SyntaxKind.CallSignature || kind === SyntaxKind.PropertySignature || kind === SyntaxKind.MethodSignature - || kind === SyntaxKind.IndexSignature - || kind === SyntaxKind.MissingDeclaration; + || kind === SyntaxKind.IndexSignature; } export function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement { @@ -5659,8 +5657,7 @@ namespace ts { || kind === SyntaxKind.SpreadAssignment || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.GetAccessor - || kind === SyntaxKind.SetAccessor - || kind === SyntaxKind.MissingDeclaration; + || kind === SyntaxKind.SetAccessor; } // Type diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index f5f60338aa9..fe1f28e1181 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1160,7 +1160,7 @@ declare namespace ts { interface DebuggerStatement extends Statement { kind: SyntaxKind.DebuggerStatement; } - interface MissingDeclaration extends DeclarationStatement, ClassElement, ObjectLiteralElement, TypeElement { + interface MissingDeclaration extends DeclarationStatement { kind: SyntaxKind.MissingDeclaration; name?: Identifier; } diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index b64ef40646c..16edf86582e 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1160,7 +1160,7 @@ declare namespace ts { interface DebuggerStatement extends Statement { kind: SyntaxKind.DebuggerStatement; } - interface MissingDeclaration extends DeclarationStatement, ClassElement, ObjectLiteralElement, TypeElement { + interface MissingDeclaration extends DeclarationStatement { kind: SyntaxKind.MissingDeclaration; name?: Identifier; } From 7c5f5249ae0a7b5be78d4f3549860e532208073d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 18 Apr 2018 11:05:56 -0700 Subject: [PATCH 39/62] Renames as per PR feedback --- src/server/project.ts | 12 ++++++------ src/server/scriptInfo.ts | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/server/project.ts b/src/server/project.ts index 653f2943d0a..92645cfca52 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -99,7 +99,7 @@ namespace ts.server { /*@internal*/ lastCachedUnresolvedImportsList: SortedReadonlyArray; /*@internal*/ - private hasMoreOrLessFiles = false; + private hasAddedorRemovedFiles = false; private lastFileExceededProgramSize: string | undefined; @@ -777,8 +777,8 @@ namespace ts.server { } /* @internal */ - setHasMoreOrLessFiles() { - this.hasMoreOrLessFiles = true; + onFileAddedOrRemoved() { + this.hasAddedorRemovedFiles = true; } /** @@ -789,8 +789,8 @@ namespace ts.server { this.resolutionCache.startRecordingFilesWithChangedResolutions(); const hasNewProgram = this.updateGraphWorker(); - const hasMoreOrLessFiles = this.hasMoreOrLessFiles; - this.hasMoreOrLessFiles = false; + const hasAddedorRemovedFiles = this.hasAddedorRemovedFiles; + this.hasAddedorRemovedFiles = false; const changedFiles: ReadonlyArray = this.resolutionCache.finishRecordingFilesWithChangedResolutions() || emptyArray; @@ -820,7 +820,7 @@ namespace ts.server { this.lastCachedUnresolvedImportsList = result ? toDeduplicatedSortedArray(result) : emptyArray; } - this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasMoreOrLessFiles); + this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasAddedorRemovedFiles); } else { this.lastCachedUnresolvedImportsList = undefined; diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index cc4ebd519e5..589975769b1 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -304,7 +304,7 @@ namespace ts.server { const isNew = !this.isAttached(project); if (isNew) { this.containingProjects.push(project); - project.setHasMoreOrLessFiles(); + project.onFileAddedOrRemoved(); if (!project.getCompilerOptions().preserveSymlinks) { this.ensureRealPath(); } @@ -329,23 +329,23 @@ namespace ts.server { return; case 1: if (this.containingProjects[0] === project) { - project.setHasMoreOrLessFiles(); + project.onFileAddedOrRemoved(); this.containingProjects.pop(); } break; case 2: if (this.containingProjects[0] === project) { - project.setHasMoreOrLessFiles(); + project.onFileAddedOrRemoved(); this.containingProjects[0] = this.containingProjects.pop(); } else if (this.containingProjects[1] === project) { - project.setHasMoreOrLessFiles(); + project.onFileAddedOrRemoved(); this.containingProjects.pop(); } break; default: if (unorderedRemoveItem(this.containingProjects, project)) { - project.setHasMoreOrLessFiles(); + project.onFileAddedOrRemoved(); } break; } From 67bb67edf15ace4122253418a339f3c08c68ee3e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 18 Apr 2018 11:22:02 -0700 Subject: [PATCH 40/62] Cache canonical global cache's package.json path --- src/server/typingsInstaller/typingsInstaller.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 0bff32958be..463851e96f4 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -83,6 +83,7 @@ namespace ts.server.typingsInstaller { private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; private readonly toCanonicalFileName: GetCanonicalFileName; + private readonly globalCacheCanonicalPackageJsonPath: string; private installRunCount = 1; private inFlightRequestCount = 0; @@ -97,6 +98,7 @@ namespace ts.server.typingsInstaller { private readonly throttleLimit: number, protected readonly log = nullLog) { this.toCanonicalFileName = createGetCanonicalFileName(installTypingHost.useCaseSensitiveFileNames); + this.globalCacheCanonicalPackageJsonPath = combinePaths(this.toCanonicalFileName(globalCachePath), "package.json"); if (this.log.isEnabled()) { this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}', types map path ${typesMapLocation}`); } @@ -440,7 +442,7 @@ namespace ts.server.typingsInstaller { return; } f = this.toCanonicalFileName(f); - if (isPackageOrBowerJson(f) && f !== this.toCanonicalFileName(combinePaths(this.globalCachePath, "package.json"))) { + if (f !== this.globalCacheCanonicalPackageJsonPath && isPackageOrBowerJson(f)) { watchers.isInvoked = true; this.sendResponse({ projectName, kind: ActionInvalidate }); } From 56b618b9fcb92a1363fcf1cced19062bfd0c3129 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 18 Apr 2018 11:44:28 -0700 Subject: [PATCH 41/62] Use indexOf and substr to exclude node_modules and bowerComponents instead of using loop --- src/server/typingsInstaller/typingsInstaller.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 463851e96f4..7d8cf02fab0 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -69,8 +69,13 @@ namespace ts.server.typingsInstaller { return base === "package.json" || base === "bower.json"; } - function isInNodeModulesOrBowerComponents(f: string) { - return stringContains(f, "/node_modules/") || stringContains(f, "/bower_components/"); + function getDirectoryExcludingNodeModulesOrBowerComponents(f: string) { + const indexOfNodeModules = f.indexOf("/node_modules/"); + const indexOfBowerComponents = f.indexOf("/bower_components/"); + const subStrLength = indexOfNodeModules === -1 || indexOfBowerComponents === -1 ? + Math.max(indexOfNodeModules, indexOfBowerComponents) : + Math.min(indexOfNodeModules, indexOfBowerComponents); + return subStrLength === -1 ? f : f.substr(0, subStrLength); } type ProjectWatchers = Map & { isInvoked?: boolean; }; @@ -478,12 +483,7 @@ namespace ts.server.typingsInstaller { } // Get path without node_modules and bower_components - let pathToWatch = getDirectoryPath(filePath); - while (isInNodeModulesOrBowerComponents(pathToWatch)) { - pathToWatch = getDirectoryPath(pathToWatch); - } - - createProjectWatcher(pathToWatch, createProjectDirectoryWatcher); + createProjectWatcher(getDirectoryExcludingNodeModulesOrBowerComponents(getDirectoryPath(filePath)), createProjectDirectoryWatcher); } // Remove unused watches From 320cb40f123d1fa1eb91cd55d9555f8c4e9d81d3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 18 Apr 2018 10:56:14 -0700 Subject: [PATCH 42/62] Address CR feedback. --- src/compiler/sys.ts | 4 ++-- src/compiler/tsc.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 2a4616732dd..be95e06eb46 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -428,7 +428,7 @@ namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; - writeOutputIsTty?(): boolean; + writeOutputIsTTY?(): boolean; readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; @@ -562,7 +562,7 @@ namespace ts { write(s: string): void { process.stdout.write(s); }, - writeOutputIsTty() { + writeOutputIsTTY() { return process.stdout.isTTY; }, readFile, diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index b2bffd83ca7..3c73eba86ef 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -25,8 +25,8 @@ namespace ts { } function shouldBePretty(options: CompilerOptions) { - if ((typeof options.pretty === "undefined")) { - return !!sys.writeOutputIsTty && sys.writeOutputIsTty(); + if (typeof options.pretty === "undefined") { + return !!sys.writeOutputIsTTY && sys.writeOutputIsTTY(); } return options.pretty; } From 25bb58124bf165354f897a817940cbdbff2c9093 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 18 Apr 2018 12:42:59 -0700 Subject: [PATCH 43/62] Accepted baselines. --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index dfe2f613078..be11525ffb7 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2888,7 +2888,7 @@ declare namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; - writeOutputIsTty?(): boolean; + writeOutputIsTTY?(): boolean; readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 6963bd95f72..c0cab668854 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2888,7 +2888,7 @@ declare namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; - writeOutputIsTty?(): boolean; + writeOutputIsTTY?(): boolean; readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; From 0e9b815956b0c3d7a110008dd3f1a1ac165259d6 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 18 Apr 2018 12:58:16 -0700 Subject: [PATCH 44/62] Improve performance of duplicate check (#23516) --- src/harness/fourslash.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 8800f78e6fd..75915c915ed 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2103,14 +2103,11 @@ Actual: ${stringify(fullActual)}`); this.raiseError("verifyRangesInImplementationList failed - expected to find at least one implementation location but got 0"); } - for (let i = 0; i < implementations.length; i++) { - for (let j = 0; j < implementations.length; j++) { - if (i !== j && implementationsAreEqual(implementations[i], implementations[j])) { - const { textSpan, fileName } = implementations[i]; - const end = textSpan.start + textSpan.length; - this.raiseError(`Duplicate implementations returned for range (${textSpan.start}, ${end}) in ${fileName}`); - } - } + const duplicate = findDuplicatedElement(implementations, implementationsAreEqual); + if (duplicate) { + const { textSpan, fileName } = duplicate; + const end = textSpan.start + textSpan.length; + this.raiseError(`Duplicate implementations returned for range (${textSpan.start}, ${end}) in ${fileName}`); } const ranges = this.getRanges(); @@ -3756,6 +3753,16 @@ ${code} function stripWhitespace(s: string): string { return s.replace(/\s/g, ""); } + + function findDuplicatedElement(a: ReadonlyArray, equal: (a: T, b: T) => boolean): T { + for (let i = 0; i < a.length; i++) { + for (let j = i + 1; j < a.length; j++) { + if (equal(a[i], a[j])) { + return a[i]; + } + } + } + } } namespace FourSlashInterface { From b271df1639102dc301ef9ab735915cc7eddb91ab Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 18 Apr 2018 12:58:40 -0700 Subject: [PATCH 45/62] Simplify getParentSymbolsOfPropertyAccess (#23513) --- src/services/findAllReferences.ts | 32 +++++++------------------------ 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 268af57e5a3..2812c051bd3 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1030,10 +1030,6 @@ namespace ts.FindAllReferences.Core { } } - function getPropertyAccessExpressionFromRightHandSide(node: Node): PropertyAccessExpression { - return isRightSideOfPropertyAccess(node) && node.parent; - } - /** * `classSymbol` is the class where the constructor was defined. * Reference the constructor and all calls to `new this()`. @@ -1130,18 +1126,6 @@ namespace ts.FindAllReferences.Core { } } - function getSymbolsForClassAndInterfaceComponents(type: UnionOrIntersectionType, result: Symbol[] = []): Symbol[] { - for (const componentType of type.types) { - if (componentType.symbol && componentType.symbol.getFlags() & (SymbolFlags.Class | SymbolFlags.Interface)) { - result.push(componentType.symbol); - } - if (componentType.isUnionOrIntersection()) { - getSymbolsForClassAndInterfaceComponents(componentType, result); - } - } - return result; - } - function getContainingTypeReference(node: Node): Node { let topLevelTypeReference: Node; @@ -1462,7 +1446,7 @@ namespace ts.FindAllReferences.Core { ? rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym : undefined, /*allowBaseTypes*/ rootSymbol => - !(search.parents && !some(search.parents, parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker)))); + !(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker)))); } /** Gets all symbols for one property. Does not get symbols for every property. */ @@ -1549,13 +1533,11 @@ namespace ts.FindAllReferences.Core { * symbol may have a different parent symbol if the local type's symbol does not declare the property * being accessed (i.e. it is declared in some parent class or interface) */ - function getParentSymbolsOfPropertyAccess(location: Node, symbol: Symbol, checker: TypeChecker): Symbol[] | undefined { - const propertyAccessExpression = getPropertyAccessExpressionFromRightHandSide(location); - const localParentType = propertyAccessExpression && checker.getTypeAtLocation(propertyAccessExpression.expression); - return localParentType && localParentType.symbol && localParentType.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) && localParentType.symbol !== symbol.parent - ? [localParentType.symbol] - : localParentType && localParentType.isUnionOrIntersection() - ? getSymbolsForClassAndInterfaceComponents(localParentType) - : undefined; + function getParentSymbolsOfPropertyAccess(location: Node, symbol: Symbol, checker: TypeChecker): ReadonlyArray | undefined { + const propertyAccessExpression = isRightSideOfPropertyAccess(location) ? location.parent : undefined; + const lhsType = propertyAccessExpression && checker.getTypeAtLocation(propertyAccessExpression.expression); + const res = mapDefined(lhsType && (lhsType.isUnionOrIntersection() ? lhsType.types : lhsType.symbol === symbol.parent ? undefined : [lhsType]), t => + t.symbol && t.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? t.symbol : undefined); + return res.length === 0 ? undefined : res; } } From 55a3c22d43d5d8c847199acd95de46852ce47c64 Mon Sep 17 00:00:00 2001 From: falsandtru Date: Thu, 19 Apr 2018 05:11:00 +0900 Subject: [PATCH 46/62] Revert "Improve PromiseConstructor" This reverts commit 4318f0d9a0bd17cf4a7c502c3fe57c8538efa5c0. --- src/lib/es2015.promise.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/es2015.promise.d.ts b/src/lib/es2015.promise.d.ts index 65986e85baf..af43abe63d6 100644 --- a/src/lib/es2015.promise.d.ts +++ b/src/lib/es2015.promise.d.ts @@ -10,7 +10,7 @@ interface PromiseConstructor { * a resolve callback used resolve the promise with a value or the result of another promise, * and a reject callback used to reject the promise with a provided reason or error. */ - new (executor: (resolve: [void] extends [T] ? (value?: T | PromiseLike) => void : (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + new (executor: (resolve: [T] extends [void] ? (value?: T | PromiseLike) => void : (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; /** * Creates a Promise that is resolved with an array of results when all of the provided Promises From 8f1bdc7e18ec7ffa7ae62571f4d5733dac193470 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 18 Apr 2018 15:24:02 -0700 Subject: [PATCH 47/62] findAllReferences: Reduce node.getSourceFile() calls (#23524) * findAllReferences: Reduce node.getSourceFile() calls * Don't create extra object --- src/services/findAllReferences.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 2812c051bd3..b7baf7166b7 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -130,8 +130,7 @@ namespace ts.FindAllReferences { const { node, name, kind, displayParts } = info; const sourceFile = node.getSourceFile(); - const textSpan = getTextSpan(isComputedPropertyName(node) ? node.expression : node, sourceFile); - return { containerKind: ScriptElementKind.unknown, containerName: "", fileName: sourceFile.fileName, kind, name, textSpan, displayParts }; + return { containerKind: ScriptElementKind.unknown, containerName: "", fileName: sourceFile.fileName, kind, name, textSpan: getTextSpan(isComputedPropertyName(node) ? node.expression : node, sourceFile), displayParts }; } function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker, node: Node): { displayParts: SymbolDisplayPart[], kind: ScriptElementKind } { @@ -148,21 +147,23 @@ namespace ts.FindAllReferences { } const { node, isInString } = entry; + const sourceFile = node.getSourceFile(); return { - fileName: node.getSourceFile().fileName, - textSpan: getTextSpan(node), + fileName: sourceFile.fileName, + textSpan: getTextSpan(node, sourceFile), isWriteAccess: isWriteAccessForReference(node), isDefinition: node.kind === SyntaxKind.DefaultKeyword || isAnyDeclarationName(node) || isLiteralComputedPropertyDeclarationName(node), - isInString + isInString, }; } function toImplementationLocation(entry: Entry, checker: TypeChecker): ImplementationLocation { if (entry.type === "node") { const { node } = entry; - return { textSpan: getTextSpan(node), fileName: node.getSourceFile().fileName, ...implementationKindDisplayParts(node, checker) }; + const sourceFile = node.getSourceFile(); + return { textSpan: getTextSpan(node, sourceFile), fileName: sourceFile.fileName, ...implementationKindDisplayParts(node, checker) }; } else { const { textSpan, fileName } = entry; @@ -199,17 +200,17 @@ namespace ts.FindAllReferences { } const { node, isInString } = entry; - const fileName = entry.node.getSourceFile().fileName; + const sourceFile = node.getSourceFile(); const writeAccess = isWriteAccessForReference(node); const span: HighlightSpan = { - textSpan: getTextSpan(node), + textSpan: getTextSpan(node, sourceFile), kind: writeAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference, isInString }; - return { fileName, span }; + return { fileName: sourceFile.fileName, span }; } - function getTextSpan(node: Node, sourceFile?: SourceFile): TextSpan { + function getTextSpan(node: Node, sourceFile: SourceFile): TextSpan { let start = node.getStart(sourceFile); let end = node.getEnd(); if (node.kind === SyntaxKind.StringLiteral) { From 2f6b59eab9e9e77c133798097b0359e5be009c53 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 18 Apr 2018 15:24:19 -0700 Subject: [PATCH 48/62] Misc. improvements to addImplementationReferences (#23507) * Misc. improvements to addImplementationReferences * Test typeHavingNode.type === typeNode * Fix bug: refNode.parent -> refNode --- src/services/findAllReferences.ts | 60 +++++++++++-------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index b7baf7166b7..60f53c2f527 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1102,57 +1102,37 @@ namespace ts.FindAllReferences.Core { } // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface - const containingTypeReference = getContainingTypeReference(refNode); - if (containingTypeReference && state.markSeenContainingTypeReference(containingTypeReference)) { - const parent = containingTypeReference.parent; - if (hasType(parent) && parent.type === containingTypeReference && hasInitializer(parent) && isImplementationExpression(parent.initializer)) { - addReference(parent.initializer); + // Find the first node whose parent isn't a type node -- i.e., the highest type node. + const typeNode = findAncestor(refNode, a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent)); + const typeHavingNode = typeNode.parent; + if (hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) { + if (hasInitializer(typeHavingNode)) { + addIfImplementation(typeHavingNode.initializer); } - else if (isFunctionLike(parent) && parent.type === containingTypeReference && (parent as FunctionLikeDeclaration).body) { - const body = (parent as FunctionLikeDeclaration).body; + else if (isFunctionLike(typeHavingNode) && (typeHavingNode as FunctionLikeDeclaration).body) { + const body = (typeHavingNode as FunctionLikeDeclaration).body; if (body.kind === SyntaxKind.Block) { forEachReturnStatement(body, returnStatement => { - if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) { - addReference(returnStatement.expression); - } + if (returnStatement.expression) addIfImplementation(returnStatement.expression); }); } - else if (isImplementationExpression(body)) { - addReference(body); + else { + addIfImplementation(body); } } - else if (isAssertionExpression(parent) && isImplementationExpression(parent.expression)) { - addReference(parent.expression); + else if (isAssertionExpression(typeHavingNode)) { + addIfImplementation(typeHavingNode.expression); } } + + function addIfImplementation(e: Expression): void { + if (isImplementationExpression(e)) addReference(e); + } } - function getContainingTypeReference(node: Node): Node { - let topLevelTypeReference: Node; - - while (node) { - if (isTypeNode(node)) { - topLevelTypeReference = node; - } - node = node.parent; - } - - return topLevelTypeReference; - } - - function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration { - if (node && node.parent) { - if (node.kind === SyntaxKind.ExpressionWithTypeArguments - && node.parent.kind === SyntaxKind.HeritageClause - && isClassLike(node.parent.parent)) { - return node.parent.parent; - } - - else if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PropertyAccessExpression) { - return getContainingClassIfInHeritageClause(node.parent); - } - } - return undefined; + function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration { + return isIdentifier(node) || isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent) + : isExpressionWithTypeArguments(node) ? tryCast(node.parent.parent, isClassLike) : undefined; } /** From 238ed7a94ca78350294548a164d75624a787e119 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 18 Apr 2018 19:52:34 -0400 Subject: [PATCH 49/62] Visit EOF to collect jsdoc import types (#23521) * Visit EOF to collect jsdoc import types * Add flag to prevent jsdoc import types from influencing compilation set --- src/compiler/program.ts | 6 +++++- .../reference/importTypeResolutionJSDocEOF.symbols | 14 ++++++++++++++ .../reference/importTypeResolutionJSDocEOF.types | 14 ++++++++++++++ .../cases/compiler/importTypeResolutionJSDocEOF.ts | 13 +++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/importTypeResolutionJSDocEOF.symbols create mode 100644 tests/baselines/reference/importTypeResolutionJSDocEOF.types create mode 100644 tests/cases/compiler/importTypeResolutionJSDocEOF.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 514397debc1..9eb82661cf5 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1624,6 +1624,9 @@ namespace ts { collectDynamicImportOrRequireCalls(node); } } + if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) { + collectDynamicImportOrRequireCalls(file.endOfFileToken); + } file.imports = imports || emptyArray; file.moduleAugmentations = moduleAugmentations || emptyArray; @@ -2004,7 +2007,8 @@ namespace ts { && !options.noResolve && i < file.imports.length && !elideImport - && !(isJsFile && !options.allowJs); + && !(isJsFile && !options.allowJs) + && (isInJavaScriptFile(file.imports[i]) || !(file.imports[i].flags & NodeFlags.JSDoc)); if (elideImport) { modulesWithElidedImports.set(file.path, true); diff --git a/tests/baselines/reference/importTypeResolutionJSDocEOF.symbols b/tests/baselines/reference/importTypeResolutionJSDocEOF.symbols new file mode 100644 index 00000000000..35a4695cb76 --- /dev/null +++ b/tests/baselines/reference/importTypeResolutionJSDocEOF.symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/interfaces.d.ts === +export interface Bar { +>Bar : Symbol(Bar, Decl(interfaces.d.ts, 0, 0)) + + prop: string +>prop : Symbol(Bar.prop, Decl(interfaces.d.ts, 0, 22)) +} + +=== tests/cases/compiler/usage.js === +/** @type {Bar} */ +export let bar; +>bar : Symbol(bar, Decl(usage.js, 1, 10)) + +/** @typedef {import('./interfaces').Bar} Bar */ diff --git a/tests/baselines/reference/importTypeResolutionJSDocEOF.types b/tests/baselines/reference/importTypeResolutionJSDocEOF.types new file mode 100644 index 00000000000..ecdafddccce --- /dev/null +++ b/tests/baselines/reference/importTypeResolutionJSDocEOF.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/interfaces.d.ts === +export interface Bar { +>Bar : Bar + + prop: string +>prop : string +} + +=== tests/cases/compiler/usage.js === +/** @type {Bar} */ +export let bar; +>bar : Bar + +/** @typedef {import('./interfaces').Bar} Bar */ diff --git a/tests/cases/compiler/importTypeResolutionJSDocEOF.ts b/tests/cases/compiler/importTypeResolutionJSDocEOF.ts new file mode 100644 index 00000000000..a900669e592 --- /dev/null +++ b/tests/cases/compiler/importTypeResolutionJSDocEOF.ts @@ -0,0 +1,13 @@ +// @allowJs: true +// @noEmit: true +// @checkJs: true +// @filename: interfaces.d.ts +export interface Bar { + prop: string +} + +// @filename: usage.js +/** @type {Bar} */ +export let bar; + +/** @typedef {import('./interfaces').Bar} Bar */ \ No newline at end of file From b8425fc596b593777003be0fcceea78a3d6b1044 Mon Sep 17 00:00:00 2001 From: csigs Date: Thu, 19 Apr 2018 16:10:34 +0000 Subject: [PATCH 50/62] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index c2b2cf32cde..b6189dcec82 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2388,15 +2388,6 @@ - - - - - - - - - @@ -3771,20 +3762,20 @@ - + - + - + - + - + - + From 557a34e897dbabdcf567cfea343c9443112fdaea Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 19 Apr 2018 10:28:30 -0700 Subject: [PATCH 51/62] Visit typedef type expressions so they contribute to referenced-ness (#23525) --- src/compiler/checker.ts | 6 ++++ .../checkJsTypeDefNoUnusedLocalMarked.symbols | 27 ++++++++++++++++ .../checkJsTypeDefNoUnusedLocalMarked.types | 32 +++++++++++++++++++ .../checkJsTypeDefNoUnusedLocalMarked.ts | 20 ++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.symbols create mode 100644 tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.types create mode 100644 tests/cases/compiler/checkJsTypeDefNoUnusedLocalMarked.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f497ba82e47..62cff0b1ce5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21865,6 +21865,11 @@ namespace ts { // If the node had `@property` tags, `typeExpression` would have been set to the first property tag. error(node.name, Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags); } + + if (node.name) { + checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0); + } + checkSourceElement(node.typeExpression); } function checkJSDocParameterTag(node: JSDocParameterTag) { @@ -24765,6 +24770,7 @@ namespace ts { case SyntaxKind.JSDocNullableType: case SyntaxKind.JSDocAllType: case SyntaxKind.JSDocUnknownType: + case SyntaxKind.JSDocTypeLiteral: checkJSDocTypeIsInJsFile(node); forEachChild(node, checkSourceElement); return; diff --git a/tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.symbols b/tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.symbols new file mode 100644 index 00000000000..6826881b834 --- /dev/null +++ b/tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/file.ts === +class Foo { +>Foo : Symbol(Foo, Decl(file.ts, 0, 0)) + + x: number; +>x : Symbol(Foo.x, Decl(file.ts, 0, 11)) +} + +declare global { +>global : Symbol(global, Decl(file.ts, 2, 1)) + + var module: any; // Just here to remove unrelated error from test +>module : Symbol(module, Decl(file.ts, 5, 7)) +} + +export = Foo; +>Foo : Symbol(Foo, Decl(file.ts, 0, 0)) + +=== tests/cases/compiler/something.js === +/** @typedef {typeof import("./file")} Foo */ + +/** @typedef {(foo: Foo) => string} FooFun */ + +module.exports = /** @type {FooFun} */(void 0); +>module : Symbol(export=, Decl(something.js, 0, 0)) +>exports : Symbol(export=, Decl(something.js, 0, 0)) + diff --git a/tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.types b/tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.types new file mode 100644 index 00000000000..1428cce142b --- /dev/null +++ b/tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.types @@ -0,0 +1,32 @@ +=== tests/cases/compiler/file.ts === +class Foo { +>Foo : Foo + + x: number; +>x : number +} + +declare global { +>global : typeof global + + var module: any; // Just here to remove unrelated error from test +>module : any +} + +export = Foo; +>Foo : Foo + +=== tests/cases/compiler/something.js === +/** @typedef {typeof import("./file")} Foo */ + +/** @typedef {(foo: Foo) => string} FooFun */ + +module.exports = /** @type {FooFun} */(void 0); +>module.exports = /** @type {FooFun} */(void 0) : (foo: typeof Foo) => string +>module.exports : any +>module : any +>exports : any +>(void 0) : (foo: typeof Foo) => string +>void 0 : undefined +>0 : 0 + diff --git a/tests/cases/compiler/checkJsTypeDefNoUnusedLocalMarked.ts b/tests/cases/compiler/checkJsTypeDefNoUnusedLocalMarked.ts new file mode 100644 index 00000000000..559e0ee7254 --- /dev/null +++ b/tests/cases/compiler/checkJsTypeDefNoUnusedLocalMarked.ts @@ -0,0 +1,20 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @noUnusedLocals: true +// @filename: file.ts +class Foo { + x: number; +} + +declare global { + var module: any; // Just here to remove unrelated error from test +} + +export = Foo; +// @filename: something.js +/** @typedef {typeof import("./file")} Foo */ + +/** @typedef {(foo: Foo) => string} FooFun */ + +module.exports = /** @type {FooFun} */(void 0); \ No newline at end of file From 8e27f4693cfe1b3e9905e37ffc9c4d37f51c3456 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 10:34:31 -0700 Subject: [PATCH 52/62] Added test for ASI concerns. --- .../templates/taggedTemplatesWithTypeArguments2.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts index 9c9bb8ee938..432e7a21748 100644 --- a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts @@ -18,3 +18,14 @@ const b = new tag `${"hello"} ${"world"}`(100, 200); const c = new tag `${100} ${200}`("hello", "world"); const d = new tag `${"hello"} ${"world"}`(100, 200); + +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +`hello`(); \ No newline at end of file From e21a8b8cfd70cd8709613a4dd4085cc98ad8a46a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 10:34:43 -0700 Subject: [PATCH 53/62] Accepted baselines. --- ...ggedTemplatesWithTypeArguments2.errors.txt | 12 ++++++++++- .../taggedTemplatesWithTypeArguments2.js | 21 ++++++++++++++++++- .../taggedTemplatesWithTypeArguments2.symbols | 13 ++++++++++++ .../taggedTemplatesWithTypeArguments2.types | 17 +++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt index 51b8bd34e0c..9dcc630e71b 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -27,4 +27,14 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30 const d = new tag `${"hello"} ${"world"}`(100, 200); ~~~~~~~ !!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. - \ No newline at end of file + + /** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ + const e = new tag + `hello`(); \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js index 33e9fef3d7f..879c274e52f 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -16,10 +16,29 @@ const b = new tag `${"hello"} ${"world"}`(100, 200); const c = new tag `${100} ${200}`("hello", "world"); const d = new tag `${"hello"} ${"world"}`(100, 200); - + +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +`hello`(); //// [taggedTemplatesWithTypeArguments2.js] const a = new tag `${100} ${200}`("hello", "world"); const b = new tag `${"hello"} ${"world"}`(100, 200); const c = (new tag `${100} ${200}`)("hello", "world"); const d = (new tag `${"hello"} ${"world"}`)(100, 200); +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag `hello`(); diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols index 720b03dd325..049b844bdf2 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols @@ -40,3 +40,16 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); >d : Symbol(d, Decl(taggedTemplatesWithTypeArguments2.ts, 16, 5)) >tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +>e : Symbol(e, Decl(taggedTemplatesWithTypeArguments2.ts, 26, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +`hello`(); diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types index cd4ff1c6e13..07afb0becc6 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -70,3 +70,20 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); >100 : 100 >200 : 200 +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +>e : any +>new tag`hello`() : any +>tag`hello` : SomethingNewable +>tag : SomethingTaggable + +`hello`(); +>`hello` : "hello" + From 6aab09a82f078fcba1f167edff489d42d4ebed0f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 19 Apr 2018 11:42:57 -0700 Subject: [PATCH 54/62] Revert change to PromiseConstructor in #22772 --- src/lib/es2015.promise.d.ts | 2 +- .../reference/defaultExportInAwaitExpression01.types | 6 +++--- .../reference/defaultExportInAwaitExpression02.types | 6 +++--- tests/baselines/reference/inferenceLimit.types | 12 ++++++------ ...dularizeLibrary_NoErrorDuplicateLibOptions1.types | 4 ++-- ...dularizeLibrary_NoErrorDuplicateLibOptions2.types | 4 ++-- .../modularizeLibrary_TargetES5UsingES6Lib.types | 4 ++-- tests/baselines/reference/usePromiseFinally.types | 4 ++-- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/lib/es2015.promise.d.ts b/src/lib/es2015.promise.d.ts index 732d8d319c2..14602c0b5ed 100644 --- a/src/lib/es2015.promise.d.ts +++ b/src/lib/es2015.promise.d.ts @@ -10,7 +10,7 @@ interface PromiseConstructor { * a resolve callback used resolve the promise with a value or the result of another promise, * and a reject callback used to reject the promise with a provided reason or error. */ - new (executor: (resolve: [T] extends [void] ? (value?: T | PromiseLike) => void : (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; /** * Creates a Promise that is resolved with an array of results when all of the provided Promises diff --git a/tests/baselines/reference/defaultExportInAwaitExpression01.types b/tests/baselines/reference/defaultExportInAwaitExpression01.types index a68e9b88fa2..1f7de76b90e 100644 --- a/tests/baselines/reference/defaultExportInAwaitExpression01.types +++ b/tests/baselines/reference/defaultExportInAwaitExpression01.types @@ -3,11 +3,11 @@ const x = new Promise( ( resolve, reject ) => { resolve( {} ); } ); >x : Promise<{}> >new Promise( ( resolve, reject ) => { resolve( {} ); } ) : Promise<{}> >Promise : PromiseConstructor ->( resolve, reject ) => { resolve( {} ); } : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value: {} | PromiseLike<{}>) => void +>( resolve, reject ) => { resolve( {} ); } : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void >resolve( {} ) : void ->resolve : (value: {} | PromiseLike<{}>) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >{} : {} export default x; diff --git a/tests/baselines/reference/defaultExportInAwaitExpression02.types b/tests/baselines/reference/defaultExportInAwaitExpression02.types index a68e9b88fa2..1f7de76b90e 100644 --- a/tests/baselines/reference/defaultExportInAwaitExpression02.types +++ b/tests/baselines/reference/defaultExportInAwaitExpression02.types @@ -3,11 +3,11 @@ const x = new Promise( ( resolve, reject ) => { resolve( {} ); } ); >x : Promise<{}> >new Promise( ( resolve, reject ) => { resolve( {} ); } ) : Promise<{}> >Promise : PromiseConstructor ->( resolve, reject ) => { resolve( {} ); } : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value: {} | PromiseLike<{}>) => void +>( resolve, reject ) => { resolve( {} ); } : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void >resolve( {} ) : void ->resolve : (value: {} | PromiseLike<{}>) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >{} : {} export default x; diff --git a/tests/baselines/reference/inferenceLimit.types b/tests/baselines/reference/inferenceLimit.types index 16e030241c2..4a398932232 100644 --- a/tests/baselines/reference/inferenceLimit.types +++ b/tests/baselines/reference/inferenceLimit.types @@ -21,8 +21,8 @@ export class BrokenClass { >Array : T[] >MyModule : any >MyModel : MyModule.MyModel ->(resolve, reject) => { let result: Array = []; let populateItems = (order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); }; return Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }); } : (resolve: (value: MyModule.MyModel[] | PromiseLike) => void, reject: (reason?: any) => void) => Promise ->resolve : (value: MyModule.MyModel[] | PromiseLike) => void +>(resolve, reject) => { let result: Array = []; let populateItems = (order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); }; return Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }); } : (resolve: (value?: MyModule.MyModel[] | PromiseLike) => void, reject: (reason?: any) => void) => Promise +>resolve : (value?: MyModule.MyModel[] | PromiseLike) => void >reject : (reason?: any) => void let result: Array = []; @@ -40,8 +40,8 @@ export class BrokenClass { return new Promise((resolve, reject) => { >new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }) : Promise<{}> >Promise : PromiseConstructor ->(resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); } : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value: {} | PromiseLike<{}>) => void +>(resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); } : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void this.doStuff(order.id) @@ -69,7 +69,7 @@ export class BrokenClass { resolve(order); >resolve(order) : void ->resolve : (value: {} | PromiseLike<{}>) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >order : any }); @@ -99,7 +99,7 @@ export class BrokenClass { resolve(orders); >resolve(orders) : void ->resolve : (value: MyModule.MyModel[] | PromiseLike) => void +>resolve : (value?: MyModule.MyModel[] | PromiseLike) => void >orders : MyModule.MyModel[] }); diff --git a/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types b/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types index bda310b20e4..78e6a6bc3f5 100644 --- a/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types +++ b/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types @@ -138,8 +138,8 @@ async function out() { return new Promise(function (resolve, reject) {}); >new Promise(function (resolve, reject) {}) : Promise<{}> >Promise : PromiseConstructor ->function (resolve, reject) {} : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value: {} | PromiseLike<{}>) => void +>function (resolve, reject) {} : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void } diff --git a/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types b/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types index 8d05cc40ce4..4aabae824ee 100644 --- a/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types +++ b/tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types @@ -138,8 +138,8 @@ async function out() { return new Promise(function (resolve, reject) {}); >new Promise(function (resolve, reject) {}) : Promise<{}> >Promise : PromiseConstructor ->function (resolve, reject) {} : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value: {} | PromiseLike<{}>) => void +>function (resolve, reject) {} : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void } diff --git a/tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types b/tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types index 9334b118d71..2782c70ebd9 100644 --- a/tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types +++ b/tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types @@ -138,8 +138,8 @@ async function out() { return new Promise(function (resolve, reject) {}); >new Promise(function (resolve, reject) {}) : Promise<{}> >Promise : PromiseConstructor ->function (resolve, reject) {} : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value: {} | PromiseLike<{}>) => void +>function (resolve, reject) {} : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void } diff --git a/tests/baselines/reference/usePromiseFinally.types b/tests/baselines/reference/usePromiseFinally.types index 2dd2d82da79..80534c75610 100644 --- a/tests/baselines/reference/usePromiseFinally.types +++ b/tests/baselines/reference/usePromiseFinally.types @@ -5,8 +5,8 @@ let promise1 = new Promise(function(resolve, reject) {}) >new Promise(function(resolve, reject) {}) .finally : (onfinally?: () => void) => Promise<{}> >new Promise(function(resolve, reject) {}) : Promise<{}> >Promise : PromiseConstructor ->function(resolve, reject) {} : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void ->resolve : (value: {} | PromiseLike<{}>) => void +>function(resolve, reject) {} : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void >reject : (reason?: any) => void .finally(function() {}); From 0f861bbfa87a60e53c001a0bd5add97b1020bcfa Mon Sep 17 00:00:00 2001 From: csigs Date: Thu, 19 Apr 2018 22:10:53 +0000 Subject: [PATCH 55/62] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index f68671fdc91..c53a7b86387 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2388,15 +2388,6 @@ - - - - - - - - - @@ -3771,20 +3762,20 @@ - + - + - + - + - + - + From 7f96fec9d97c88ef95d0aad803db817c8d391e22 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 14:27:48 -0700 Subject: [PATCH 56/62] Added test in case 'super' is ever possibly parsed as a tagged template string. --- .../templates/taggedTemplatesWithTypeArguments2.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts index 432e7a21748..a7a0044d93d 100644 --- a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts @@ -28,4 +28,14 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); * ``` */ const e = new tag -`hello`(); \ No newline at end of file +`hello`(); + +class SomeBase { + a!: A; b!: B; c!: C; +} + +class SomeDerived extends SomeBase { + constructor() { + super `hello world`; + } +} \ No newline at end of file From 70feb7b10ba771a8b137b643046dbb85350cd090 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 14:29:53 -0700 Subject: [PATCH 57/62] Avoid duplicate code when checking for tagged templates. --- src/compiler/checker.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 60fcf103041..b65d153aa45 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17749,15 +17749,11 @@ namespace ts { let typeArguments: NodeArray; - if (isTaggedTemplate) { - typeArguments = (node as TaggedTemplateExpression).typeArguments; - forEach(typeArguments, checkSourceElement); - } - else if (!isDecorator && !isJsxOpeningOrSelfClosingElement) { + if (!isDecorator && !isJsxOpeningOrSelfClosingElement) { typeArguments = (node).typeArguments; // We already perform checking on the type arguments on the class declaration itself. - if ((node).expression.kind !== SyntaxKind.SuperKeyword) { + if (isTaggedTemplate || (node).expression.kind !== SyntaxKind.SuperKeyword) { forEach(typeArguments, checkSourceElement); } } From 87bb96d7b24f6cb27dafddde6de80476d3a4dd5a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 19 Apr 2018 15:15:53 -0700 Subject: [PATCH 58/62] Accepted baselines. --- ...ggedTemplatesWithTypeArguments2.errors.txt | 25 +++++++++++++-- .../taggedTemplatesWithTypeArguments2.js | 19 +++++++++++- .../taggedTemplatesWithTypeArguments2.symbols | 28 +++++++++++++++++ .../taggedTemplatesWithTypeArguments2.types | 31 +++++++++++++++++++ 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt index 9dcc630e71b..44607433031 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -1,9 +1,12 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2347: Untyped function calls may not accept type arguments. tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(35,5): error TS2377: Constructors for derived classes must contain a 'super' call. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(36,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(36,14): error TS1034: 'super' must be followed by an argument list or member access. -==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (3 errors) ==== +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (6 errors) ==== export interface SomethingTaggable { (t: TemplateStringsArray, ...args: T[]): SomethingNewable; } @@ -37,4 +40,22 @@ tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30 * ``` */ const e = new tag - `hello`(); \ No newline at end of file + `hello`(); + + class SomeBase { + a!: A; b!: B; c!: C; + } + + class SomeDerived extends SomeBase { + constructor() { + ~~~~~~~~~~~~~~~ + super `hello world`; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~ +!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. + ~ +!!! error TS1034: 'super' must be followed by an argument list or member access. + } + ~~~~~ +!!! error TS2377: Constructors for derived classes must contain a 'super' call. + } \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js index 879c274e52f..bc170467fa8 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -26,7 +26,17 @@ const d = new tag `${"hello"} ${"world"}`(100, 200); * ``` */ const e = new tag -`hello`(); +`hello`(); + +class SomeBase { + a!: A; b!: B; c!: C; +} + +class SomeDerived extends SomeBase { + constructor() { + super `hello world`; + } +} //// [taggedTemplatesWithTypeArguments2.js] const a = new tag `${100} ${200}`("hello", "world"); @@ -42,3 +52,10 @@ const d = (new tag `${"hello"} ${"world"}`)(100, 200); * ``` */ const e = new tag `hello`(); +class SomeBase { +} +class SomeDerived extends SomeBase { + constructor() { + super. `hello world`; + } +} diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols index 049b844bdf2..631770a30dd 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols @@ -53,3 +53,31 @@ const e = new tag >tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) `hello`(); + +class SomeBase { +>SomeBase : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>A : Symbol(A, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 15)) +>B : Symbol(B, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 17)) +>C : Symbol(C, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 20)) + + a!: A; b!: B; c!: C; +>a : Symbol(SomeBase.a, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 25)) +>A : Symbol(A, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 15)) +>b : Symbol(SomeBase.b, Decl(taggedTemplatesWithTypeArguments2.ts, 30, 10)) +>B : Symbol(B, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 17)) +>c : Symbol(SomeBase.c, Decl(taggedTemplatesWithTypeArguments2.ts, 30, 17)) +>C : Symbol(C, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 20)) +} + +class SomeDerived extends SomeBase { +>SomeDerived : Symbol(SomeDerived, Decl(taggedTemplatesWithTypeArguments2.ts, 31, 1)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) +>SomeBase : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) + + constructor() { + super `hello world`; +>super : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) + } +} diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types index 07afb0becc6..8aef2009d1b 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -87,3 +87,34 @@ const e = new tag `hello`(); >`hello` : "hello" +class SomeBase { +>SomeBase : SomeBase +>A : A +>B : B +>C : C + + a!: A; b!: B; c!: C; +>a : A +>A : A +>b : B +>B : B +>c : C +>C : C +} + +class SomeDerived extends SomeBase { +>SomeDerived : SomeDerived +>T : T +>SomeBase : SomeBase +>T : T + + constructor() { + super `hello world`; +>super `hello world` : any +>super : any +>super : SomeBase +> : any +>T : T +>`hello world` : "hello world" + } +} From bc7979c1743f946f5366ca2893d1bd4c50633d8d Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 19 Apr 2018 15:33:36 -0700 Subject: [PATCH 59/62] quickInfo: Get JSDoc tags from aliased symbol (#23526) * quickInfo: Get JSDoc tags from aliased symbol * Add test with existing tags --- src/services/symbolDisplay.ts | 5 +++ tests/cases/fourslash/fourslash.ts | 2 +- tests/cases/fourslash/quickInfoAlias.ts | 51 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/quickInfoAlias.ts diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index f79c048efad..7abb89befd7 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -134,6 +134,7 @@ namespace ts.SymbolDisplay { let type: Type; let printer: Printer; let documentationFromAlias: SymbolDisplayPart[]; + let tagsFromAlias: JSDocTagInfo[]; // Class at constructor site need to be shown as constructor apart from property,method, vars if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Alias) { @@ -396,6 +397,7 @@ namespace ts.SymbolDisplay { displayParts.push(...resolvedInfo.displayParts); displayParts.push(lineBreakPart()); documentationFromAlias = resolvedInfo.documentation; + tagsFromAlias = resolvedInfo.tags; } } } @@ -521,6 +523,9 @@ namespace ts.SymbolDisplay { if (documentation.length === 0 && documentationFromAlias) { documentation = documentationFromAlias; } + if (tags.length === 0 && tagsFromAlias) { + tags = tagsFromAlias; + } return { displayParts, documentation, symbolKind, tags }; diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index e756bd22fae..697d2d72555 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -338,7 +338,7 @@ declare namespace FourSlashInterface { verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; - }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: ts.JSDocTagInfo[]): void; + }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: { name: string, text?: string }[]): void; getSyntacticDiagnostics(expected: ReadonlyArray): void; getSemanticDiagnostics(expected: ReadonlyArray): void; getSuggestionDiagnostics(expected: ReadonlyArray): void; diff --git a/tests/cases/fourslash/quickInfoAlias.ts b/tests/cases/fourslash/quickInfoAlias.ts new file mode 100644 index 00000000000..cfbe8ed3692 --- /dev/null +++ b/tests/cases/fourslash/quickInfoAlias.ts @@ -0,0 +1,51 @@ +/// + +// @Filename: /a.ts +/////** +//// * Doc +//// * @tag Tag text +//// */ +////export const x = 0; + +// @Filename: /b.ts +////import { x } from "./a"; +////x/*b*/; + +// @Filename: /c.ts +/////** +//// * Doc 2 +//// * @tag Tag text 2 +//// */ +////import { +//// /** +//// * Doc 3 +//// * @tag Tag text 3 +//// */ +//// x +////} from "./a"; +////x/*c*/; + +goTo.eachMarker((_, index) => { + verify.verifyQuickInfoDisplayParts( + "alias", + "", + { start: index === 0 ? 25 : 117, length: 1 }, + [ + { text:"(",kind:"punctuation" }, + { text:"alias",kind:"text" }, + { text:")",kind:"punctuation" }, + { text:" ",kind:"space" }, + { text:"const",kind:"keyword" }, + { text:" ",kind:"space" }, + { text:"x",kind:"aliasName" }, + { text:":",kind:"punctuation" }, + { text:" ",kind:"space" }, + { text:"0",kind:"stringLiteral" }, + { text:"\n",kind:"lineBreak" }, + { text:"import",kind:"keyword" }, + { text:" ",kind:"space" }, + { text:"x",kind:"aliasName" }, + ], + [{ text: "Doc", kind: "text" }], + [{ name: "tag", text: "Tag text" }]); +}); From c258d6e1b65f5a0e66bac07ed61b6845baf536f1 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 19 Apr 2018 15:35:25 -0700 Subject: [PATCH 60/62] Fix bug: Don't rename 'default' in `export { default as x } from "m";` (#23434) * Fix bug: Don't rename 'default' in `export { default as x } from "m";` * Rename `foo` in `{ default as foo }` if that's the original export name --- src/services/findAllReferences.ts | 10 ++++++++-- src/services/importTracker.ts | 6 ++++-- .../findAllRefsRenameImportWithSameName.ts | 5 +++-- .../cases/fourslash/renameReExportDefault.ts | 19 +++++++++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 tests/cases/fourslash/renameReExportDefault.ts diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 60f53c2f527..57fe2a7a0e4 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -555,7 +555,10 @@ namespace ts.FindAllReferences.Core { if (singleReferences.length) { const addRef = state.referenceAdder(exportSymbol); for (const singleRef of singleReferences) { - addRef(singleRef); + // At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename. + if (!(state.options.isForRename && (isExportSpecifier(singleRef.parent) || isImportSpecifier(singleRef.parent)) && singleRef.escapedText === InternalSymbolName.Default)) { + addRef(singleRef); + } } } @@ -887,7 +890,10 @@ namespace ts.FindAllReferences.Core { } if (!propertyName) { - addRef(); + // Don't rename at `export { default } from "m";`. (but do continue to search for imports of the re-export) + if (!(state.options.isForRename && name.escapedText === InternalSymbolName.Default)) { + addRef(); + } } else if (referenceLocation === propertyName) { // For `export { foo as bar } from "baz"`, "`foo`" will be added from the singleReferences for import searches of the original export. diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 80f0721e642..1a4b2a9f751 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -254,7 +254,7 @@ namespace ts.FindAllReferences { } // 'default' might be accessed as a named import `{ default as foo }`. - if (!isForRename && exportKind === ExportKind.Default) { + if (exportKind === ExportKind.Default) { searchForNamedImport(namedBindings as NamedImports | undefined); } } @@ -286,7 +286,9 @@ namespace ts.FindAllReferences { if (propertyName) { // This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference. singleReferences.push(propertyName); - if (!isForRename) { // If renaming `foo`, don't touch `bar`, just `foo`. + // If renaming `{ foo as bar }`, don't touch `bar`, just `foo`. + // But do rename `foo` in ` { default as foo }` if that's the original export name. + if (!isForRename || name.escapedText === exportSymbol.escapedName) { // Search locally for `bar`. addSearch(name, checker.getSymbolAtLocation(name)); } diff --git a/tests/cases/fourslash/findAllRefsRenameImportWithSameName.ts b/tests/cases/fourslash/findAllRefsRenameImportWithSameName.ts index 62b1c19c5ed..38c3aaf9398 100644 --- a/tests/cases/fourslash/findAllRefsRenameImportWithSameName.ts +++ b/tests/cases/fourslash/findAllRefsRenameImportWithSameName.ts @@ -16,5 +16,6 @@ const bGroup = { definition: "(alias) const x: 0\nimport x", ranges: bRanges }; verify.referenceGroups(aRanges, [aGroup, bGroup]); verify.referenceGroups(bRanges, [bGroup]); -verify.rangesAreRenameLocations(aRanges); -verify.rangesAreRenameLocations(aRanges); +verify.renameLocations(r0, [r0, r1, r2, r3]); +verify.renameLocations(r1, [r0, r1, r2, r3]); +verify.rangesAreRenameLocations([r2, r3]); diff --git a/tests/cases/fourslash/renameReExportDefault.ts b/tests/cases/fourslash/renameReExportDefault.ts new file mode 100644 index 00000000000..0eb5b81d209 --- /dev/null +++ b/tests/cases/fourslash/renameReExportDefault.ts @@ -0,0 +1,19 @@ +/// + +// @Filename: /a.ts +////export { default } from "./b"; +////export { default as [|b|] } from "./b"; +////export { default as bee } from "./b"; +////import { default as [|b|] } from "./b"; +////import { default as bee } from "./b"; +////import [|b|] from "./b"; + +// @Filename: /b.ts +////const [|b|] = 0; +////export default [|b|]; + +const [r0, r1, r2, r3, r4] = test.ranges(); +verify.renameLocations(r0, [r0]); +verify.renameLocations(r1, [r1]); +verify.renameLocations(r2, [r2]); +verify.renameLocations([r3, r4], [r0, r1, r2, r3, r4]); From a7c08e4691584e6d2fac55b3dccdd88936ecda6a Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 19 Apr 2018 15:39:44 -0700 Subject: [PATCH 61/62] Make code fix to add 'this.' work for statics (#23527) * Make code fix to add 'this.' work for statics * Add 'C.' instead of 'this.' * DanielRosenwasser code review --- src/compiler/diagnosticMessages.json | 4 +-- .../fixForgottenThisPropertyAccess.ts | 31 ++++++++++--------- .../codeFixForgottenThisPropertyAccess_all.ts | 2 +- ...deFixForgottenThisPropertyAccess_static.ts | 25 +++++++++++++++ 4 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 235788258af..a5119f7feb7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3914,7 +3914,7 @@ "category": "Message", "code": 90007 }, - "Add 'this.' to unresolved variable": { + "Add '{0}.' to unresolved variable": { "category": "Message", "code": 90008 }, @@ -4122,7 +4122,7 @@ "category": "Message", "code": 95036 }, - "Add 'this.' to all unresolved variables matching a member name": { + "Add qualifier to all unresolved variables matching a member name": { "category": "Message", "code": 95037 }, diff --git a/src/services/codefixes/fixForgottenThisPropertyAccess.ts b/src/services/codefixes/fixForgottenThisPropertyAccess.ts index b26e4c7cdca..31c6128d003 100644 --- a/src/services/codefixes/fixForgottenThisPropertyAccess.ts +++ b/src/services/codefixes/fixForgottenThisPropertyAccess.ts @@ -1,35 +1,38 @@ /* @internal */ namespace ts.codefix { const fixId = "forgottenThisPropertyAccess"; - const errorCodes = [Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code]; + const didYouMeanStaticMemberCode = Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code; + const errorCodes = [ + Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code, + didYouMeanStaticMemberCode, + ]; registerCodeFix({ errorCodes, getCodeActions(context) { const { sourceFile } = context; - const token = getNode(sourceFile, context.span.start); - if (!token) { + const info = getInfo(sourceFile, context.span.start, context.errorCode); + if (!info) { return undefined; } - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, token)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_this_to_unresolved_variable, fixId, Diagnostics.Add_this_to_all_unresolved_variables_matching_a_member_name)]; + const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info)); + return [createCodeFixAction(fixId, changes, [Diagnostics.Add_0_to_unresolved_variable, info.className || "this"], fixId, Diagnostics.Add_qualifier_to_all_unresolved_variables_matching_a_member_name)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { - doChange(changes, context.sourceFile, getNode(diag.file, diag.start!)); + doChange(changes, context.sourceFile, getInfo(diag.file, diag.start!, diag.code)); }), }); - function getNode(sourceFile: SourceFile, pos: number): Identifier | undefined { + interface Info { readonly node: Identifier; readonly className: string | undefined; } + function getInfo(sourceFile: SourceFile, pos: number, diagCode: number): Info | undefined { const node = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); - return isIdentifier(node) ? node : undefined; + if (!isIdentifier(node)) return undefined; + return { node, className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node).name.text : undefined }; } - function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Identifier | undefined): void { - if (!token) { - return; - } + function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node, className }: Info): void { // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper - suppressLeadingAndTrailingTrivia(token); - changes.replaceNode(sourceFile, token, createPropertyAccess(createThis(), token)); + suppressLeadingAndTrailingTrivia(node); + changes.replaceNode(sourceFile, node, createPropertyAccess(className ? createIdentifier(className) : createThis(), node)); } } diff --git a/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_all.ts b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_all.ts index ab95f6b3355..65d44dd8fdb 100644 --- a/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_all.ts +++ b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_all.ts @@ -10,7 +10,7 @@ verify.codeFixAll({ fixId: "forgottenThisPropertyAccess", - fixAllDescription: "Add 'this.' to all unresolved variables matching a member name", + fixAllDescription: "Add qualifier to all unresolved variables matching a member name", newFileContent: `class C { foo: number; diff --git a/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts new file mode 100644 index 00000000000..cc6f8032a51 --- /dev/null +++ b/tests/cases/fourslash/codeFixForgottenThisPropertyAccess_static.ts @@ -0,0 +1,25 @@ +/// + +////class C { +//// static m() { m(); } +//// n() { m(); } +////} + +verify.codeFix({ + description: "Add 'C.' to unresolved variable", + index: 0, + newFileContent: +`class C { + static m() { C.m(); } + n() { m(); } +}` +}); + +verify.codeFix({ + description: "Add 'C.' to unresolved variable", + newFileContent: +`class C { + static m() { C.m(); } + n() { C.m(); } +}` +}); From 8d969a23cba2cec9ce3baa5e1cfaafda2c7c0301 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 19 Apr 2018 15:58:43 -0700 Subject: [PATCH 62/62] In JS, class supports `@template` tag for declaring type parameters (#23511) * Support @template as a class type parameter Still need to do the following: 1. Correctly get jsdoc host in predicate. 2. Make this work for constructor functions too. 3. Scan rest of codebase for other usages of the type parameters property that should be calls to getEffectiveTypeParameterDeclarations. 4. Rename tp to something more readable, like typar or ts'. * Use jsdoc host declaration to find container * Longer names for type parameters * Fix renaming operation * Update fourslash test * Support @template for JS constructors * Look for both outer and tag type parameters * Improve naming to improve code clarity --- src/compiler/checker.ts | 72 +++++++++++------- src/compiler/utilities.ts | 4 +- .../reference/jsdocTemplateClass.errors.txt | 31 ++++++++ .../reference/jsdocTemplateClass.symbols | 54 +++++++++++++ .../reference/jsdocTemplateClass.types | 62 +++++++++++++++ ...sdocTemplateConstructorFunction.errors.txt | 28 +++++++ .../jsdocTemplateConstructorFunction.symbols | 57 ++++++++++++++ .../jsdocTemplateConstructorFunction.types | 76 +++++++++++++++++++ .../conformance/jsdoc/jsdocTemplateClass.ts | 29 +++++++ .../jsdoc/jsdocTemplateConstructorFunction.ts | 26 +++++++ .../findAllRefsJsDocTemplateTag_class_js.ts | 5 +- 11 files changed, 413 insertions(+), 31 deletions(-) create mode 100644 tests/baselines/reference/jsdocTemplateClass.errors.txt create mode 100644 tests/baselines/reference/jsdocTemplateClass.symbols create mode 100644 tests/baselines/reference/jsdocTemplateClass.types create mode 100644 tests/baselines/reference/jsdocTemplateConstructorFunction.errors.txt create mode 100644 tests/baselines/reference/jsdocTemplateConstructorFunction.symbols create mode 100644 tests/baselines/reference/jsdocTemplateConstructorFunction.types create mode 100644 tests/cases/conformance/jsdoc/jsdocTemplateClass.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocTemplateConstructorFunction.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6c8a79daf5f..bfc9c1fd550 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1554,7 +1554,8 @@ namespace ts { function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { for (const decl of symbol.declarations) { - if (decl.kind === SyntaxKind.TypeParameter && decl.parent === container) { + const parent = isJSDocTemplateTag(decl.parent) ? getJSDocHost(decl.parent) : decl.parent; + if (decl.kind === SyntaxKind.TypeParameter && parent === container) { return true; } } @@ -2060,10 +2061,10 @@ namespace ts { let symbol: Symbol; if (name.kind === SyntaxKind.Identifier) { const message = meaning === namespaceMeaning ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0; - - symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors ? undefined : message, name, /*isUse*/ true); + const symbolFromJSPrototype = isInJavaScriptFile(name) && resolveEntityNameFromJSPrototype(name, meaning); + symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true); if (!symbol) { - return undefined; + return symbolFromJSPrototype; } } else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) { @@ -2114,6 +2115,18 @@ namespace ts { return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol); } + function resolveEntityNameFromJSPrototype(name: Identifier, meaning: SymbolFlags) { + if (isJSDocTypeReference(name.parent) && isJSDocTag(name.parent.parent.parent)) { + const host = getJSDocHost(name.parent.parent.parent as JSDocTag); + if (isExpressionStatement(host) && + isBinaryExpression(host.expression) && + getSpecialPropertyAssignmentKind(host.expression) === SpecialPropertyAssignmentKind.PrototypeProperty) { + const secondaryLocation = getSymbolOfNode(host.expression.left).parent.valueDeclaration; + return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true); + } + } + } + function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol { return resolveExternalModuleNameWorker(location, moduleReferenceExpression, Diagnostics.Cannot_find_module_0); } @@ -4897,8 +4910,7 @@ namespace ts { // in-place and returns the same array. function appendTypeParameters(typeParameters: TypeParameter[], declarations: ReadonlyArray): TypeParameter[] { for (const declaration of declarations) { - const tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration)); - typeParameters = appendIfUnique(typeParameters, tp); + typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration))); } return typeParameters; } @@ -4958,8 +4970,9 @@ namespace ts { if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.TypeAliasDeclaration) { const declaration = node; - if (declaration.typeParameters) { - result = appendTypeParameters(result, declaration.typeParameters); + const typeParameters = getEffectiveTypeParameterDeclarations(declaration); + if (typeParameters) { + result = appendTypeParameters(result, typeParameters); } } } @@ -5455,9 +5468,10 @@ namespace ts { */ function isThislessFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { const returnType = getEffectiveReturnTypeNode(node); + const typeParameters = getEffectiveTypeParameterDeclarations(node); return (node.kind === SyntaxKind.Constructor || (returnType && isThislessType(returnType))) && node.parameters.every(isThislessVariableLikeDeclaration) && - (!node.typeParameters || node.typeParameters.every(isThislessTypeParameter)); + (!typeParameters || typeParameters.every(isThislessTypeParameter)); } /** @@ -6735,8 +6749,7 @@ namespace ts { function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): TypeParameter[] { let result: TypeParameter[]; forEach(getEffectiveTypeParameterDeclarations(declaration), node => { - const tp = getDeclaredTypeOfTypeParameter(node.symbol); - result = appendIfUnique(result, tp); + result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol)); }); return result; } @@ -7547,7 +7560,7 @@ namespace ts { return constraints ? getSubstitutionType(typeVariable, getIntersectionType(append(constraints, typeVariable))) : typeVariable; } - function isJSDocTypeReference(node: NodeWithTypeArguments): node is TypeReferenceNode { + function isJSDocTypeReference(node: Node): node is TypeReferenceNode { return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference; } @@ -9170,10 +9183,15 @@ namespace ts { // aren't the right hand side of a generic type alias declaration we optimize by reducing the // set of type parameters to those that are possibly referenced in the literal. const declaration = symbol.declarations[0]; - const outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true) || emptyArray; + let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true); + if (isJavaScriptConstructor(declaration)) { + const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters); + outerTypeParameters = addRange(outerTypeParameters, templateTagParameters); + } + typeParameters = outerTypeParameters || emptyArray; typeParameters = symbol.flags & SymbolFlags.TypeLiteral && !target.aliasTypeArguments ? - filter(outerTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, declaration)) : - outerTypeParameters; + filter(typeParameters, tp => isTypeParameterPossiblyReferenced(tp, declaration)) : + typeParameters; links.outerTypeParameters = typeParameters; if (typeParameters.length) { links.instantiations = createMap(); @@ -18533,7 +18551,7 @@ namespace ts { } const type = funcSymbol && getJavaScriptClassType(funcSymbol); if (type) { - return type; + return signature.target ? instantiateType(type, signature.mapper) : type; } if (noImplicitAny) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); @@ -22161,8 +22179,9 @@ namespace ts { ): void { // Only report errors on the last declaration for the type parameter container; // this ensures that all uses have been accounted for. - if (!(node.flags & NodeFlags.Ambient) && node.typeParameters && last(getSymbolOfNode(node)!.declarations) === node) { - for (const typeParameter of node.typeParameters) { + const typeParameters = getEffectiveTypeParameterDeclarations(node); + if (!(node.flags & NodeFlags.Ambient) && typeParameters && last(getSymbolOfNode(node)!.declarations) === node) { + for (const typeParameter of typeParameters) { if (!(getMergedSymbol(typeParameter.symbol).isReferenced & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { addDiagnostic(UnusedKind.Parameter, createDiagnosticForNode(typeParameter.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(typeParameter.symbol))); } @@ -23536,20 +23555,21 @@ namespace ts { } } - function areTypeParametersIdentical(declarations: ReadonlyArray, typeParameters: TypeParameter[]) { - const maxTypeArgumentCount = length(typeParameters); - const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); + function areTypeParametersIdentical(declarations: ReadonlyArray, targetParameters: TypeParameter[]) { + const maxTypeArgumentCount = length(targetParameters); + const minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); for (const declaration of declarations) { // If this declaration has too few or too many type parameters, we report an error - const numTypeParameters = length(declaration.typeParameters); + const sourceParameters = getEffectiveTypeParameterDeclarations(declaration); + const numTypeParameters = length(sourceParameters); if (numTypeParameters < minTypeArgumentCount || numTypeParameters > maxTypeArgumentCount) { return false; } for (let i = 0; i < numTypeParameters; i++) { - const source = declaration.typeParameters[i]; - const target = typeParameters[i]; + const source = sourceParameters[i]; + const target = targetParameters[i]; // If the type parameter node does not have the same as the resolved type // parameter at this position, we report an error. @@ -23610,7 +23630,7 @@ namespace ts { checkCollisionWithRequireExportsInGeneratedCode(node, node.name); checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name); } - checkTypeParameters(node.typeParameters); + checkTypeParameters(getEffectiveTypeParameterDeclarations(node)); checkExportsOnMergedDeclarations(node); const symbol = getSymbolOfNode(node); const type = getDeclaredTypeOfSymbol(symbol); @@ -26846,7 +26866,7 @@ namespace ts { function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean { const file = getSourceFileOfNode(node); - return checkGrammarClassDeclarationHeritageClauses(node) || checkGrammarTypeParameterList(node.typeParameters, file); + return checkGrammarClassDeclarationHeritageClauses(node) || checkGrammarTypeParameterList(getEffectiveTypeParameterDeclarations(node), file); } function checkGrammarArrowFunction(node: Node, file: SourceFile): boolean { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3fe255fb612..730c3fc51d4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3055,11 +3055,11 @@ namespace ts { * Gets the effective type parameters. If the node was parsed in a * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. */ - export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): ReadonlyArray | undefined { + export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters) { return node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined); } - export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters): ReadonlyArray { + export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters) { const templateTag = getJSDocTemplateTag(node); return templateTag && templateTag.typeParameters; } diff --git a/tests/baselines/reference/jsdocTemplateClass.errors.txt b/tests/baselines/reference/jsdocTemplateClass.errors.txt new file mode 100644 index 00000000000..4598e9f320f --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateClass.errors.txt @@ -0,0 +1,31 @@ +tests/cases/conformance/jsdoc/templateTagOnClasses.js(24,1): error TS2322: Type 'boolean' is not assignable to type 'number'. + + +==== tests/cases/conformance/jsdoc/templateTagOnClasses.js (1 errors) ==== + /** + * @template {T} + * @typedef {(t: T) => T} Id + */ + class Foo { + /** @typedef {(t: T) => T} Id2 */ + /** @param {T} x */ + constructor (x) { + this.a = x + } + /** + * + * @param {T} x + * @param {Id} y + * @param {Id2} alpha + * @return {T} + */ + foo(x, y, alpha) { + return alpha(y(x)) + } + } + var f = new Foo(1) + var g = new Foo(false) + f.a = g.a + ~~~ +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocTemplateClass.symbols b/tests/baselines/reference/jsdocTemplateClass.symbols new file mode 100644 index 00000000000..d80b73bc4ac --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateClass.symbols @@ -0,0 +1,54 @@ +=== tests/cases/conformance/jsdoc/templateTagOnClasses.js === +/** + * @template {T} + * @typedef {(t: T) => T} Id + */ +class Foo { +>Foo : Symbol(Foo, Decl(templateTagOnClasses.js, 0, 0)) + + /** @typedef {(t: T) => T} Id2 */ + /** @param {T} x */ + constructor (x) { +>x : Symbol(x, Decl(templateTagOnClasses.js, 7, 17)) + + this.a = x +>this.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21)) +>this : Symbol(Foo, Decl(templateTagOnClasses.js, 0, 0)) +>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21)) +>x : Symbol(x, Decl(templateTagOnClasses.js, 7, 17)) + } + /** + * + * @param {T} x + * @param {Id} y + * @param {Id2} alpha + * @return {T} + */ + foo(x, y, alpha) { +>foo : Symbol(Foo.foo, Decl(templateTagOnClasses.js, 9, 5)) +>x : Symbol(x, Decl(templateTagOnClasses.js, 17, 8)) +>y : Symbol(y, Decl(templateTagOnClasses.js, 17, 10)) +>alpha : Symbol(alpha, Decl(templateTagOnClasses.js, 17, 13)) + + return alpha(y(x)) +>alpha : Symbol(alpha, Decl(templateTagOnClasses.js, 17, 13)) +>y : Symbol(y, Decl(templateTagOnClasses.js, 17, 10)) +>x : Symbol(x, Decl(templateTagOnClasses.js, 17, 8)) + } +} +var f = new Foo(1) +>f : Symbol(f, Decl(templateTagOnClasses.js, 21, 3)) +>Foo : Symbol(Foo, Decl(templateTagOnClasses.js, 0, 0)) + +var g = new Foo(false) +>g : Symbol(g, Decl(templateTagOnClasses.js, 22, 3)) +>Foo : Symbol(Foo, Decl(templateTagOnClasses.js, 0, 0)) + +f.a = g.a +>f.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21)) +>f : Symbol(f, Decl(templateTagOnClasses.js, 21, 3)) +>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21)) +>g.a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21)) +>g : Symbol(g, Decl(templateTagOnClasses.js, 22, 3)) +>a : Symbol(Foo.a, Decl(templateTagOnClasses.js, 7, 21)) + diff --git a/tests/baselines/reference/jsdocTemplateClass.types b/tests/baselines/reference/jsdocTemplateClass.types new file mode 100644 index 00000000000..aa6a685e34f --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateClass.types @@ -0,0 +1,62 @@ +=== tests/cases/conformance/jsdoc/templateTagOnClasses.js === +/** + * @template {T} + * @typedef {(t: T) => T} Id + */ +class Foo { +>Foo : Foo + + /** @typedef {(t: T) => T} Id2 */ + /** @param {T} x */ + constructor (x) { +>x : T + + this.a = x +>this.a = x : T +>this.a : T +>this : this +>a : T +>x : T + } + /** + * + * @param {T} x + * @param {Id} y + * @param {Id2} alpha + * @return {T} + */ + foo(x, y, alpha) { +>foo : (x: T, y: (t: T) => T, alpha: (t: T) => T) => T +>x : T +>y : (t: T) => T +>alpha : (t: T) => T + + return alpha(y(x)) +>alpha(y(x)) : T +>alpha : (t: T) => T +>y(x) : T +>y : (t: T) => T +>x : T + } +} +var f = new Foo(1) +>f : Foo +>new Foo(1) : Foo +>Foo : typeof Foo +>1 : 1 + +var g = new Foo(false) +>g : Foo +>new Foo(false) : Foo +>Foo : typeof Foo +>false : false + +f.a = g.a +>f.a = g.a : boolean +>f.a : number +>f : Foo +>a : number +>g.a : boolean +>g : Foo +>a : boolean + diff --git a/tests/baselines/reference/jsdocTemplateConstructorFunction.errors.txt b/tests/baselines/reference/jsdocTemplateConstructorFunction.errors.txt new file mode 100644 index 00000000000..225d277c4ff --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateConstructorFunction.errors.txt @@ -0,0 +1,28 @@ +tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js(21,1): error TS2322: Type 'false' is not assignable to type 'number'. + + +==== tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js (1 errors) ==== + /** + * @template {T} + * @typedef {(t: T) => T} Id + * @param {T} t + */ + function Zet(t) { + /** @type {T} */ + this.u + this.t = t + } + /** + * @param {T} v + * @param {Id} id + */ + Zet.prototype.add = function(v, id) { + this.u = v || this.t + return id(this.u) + } + var z = new Zet(1) + z.t = 2 + z.u = false + ~~~ +!!! error TS2322: Type 'false' is not assignable to type 'number'. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocTemplateConstructorFunction.symbols b/tests/baselines/reference/jsdocTemplateConstructorFunction.symbols new file mode 100644 index 00000000000..8cf2ee99e57 --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateConstructorFunction.symbols @@ -0,0 +1,57 @@ +=== tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js === +/** + * @template {T} + * @typedef {(t: T) => T} Id + * @param {T} t + */ +function Zet(t) { +>Zet : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0)) +>t : Symbol(t, Decl(templateTagOnConstructorFunctions.js, 5, 13)) + + /** @type {T} */ + this.u + this.t = t +>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10)) +>t : Symbol(t, Decl(templateTagOnConstructorFunctions.js, 5, 13)) +} +/** + * @param {T} v + * @param {Id} id + */ +Zet.prototype.add = function(v, id) { +>Zet.prototype : Symbol(Zet.add, Decl(templateTagOnConstructorFunctions.js, 9, 1)) +>Zet : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0)) +>prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --)) +>add : Symbol(Zet.add, Decl(templateTagOnConstructorFunctions.js, 9, 1)) +>v : Symbol(v, Decl(templateTagOnConstructorFunctions.js, 14, 29)) +>id : Symbol(id, Decl(templateTagOnConstructorFunctions.js, 14, 31)) + + this.u = v || this.t +>this.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37)) +>this : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0)) +>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37)) +>v : Symbol(v, Decl(templateTagOnConstructorFunctions.js, 14, 29)) +>this.t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10)) +>this : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0)) +>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10)) + + return id(this.u) +>id : Symbol(id, Decl(templateTagOnConstructorFunctions.js, 14, 31)) +>this.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37)) +>this : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0)) +>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37)) +} +var z = new Zet(1) +>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 18, 3)) +>Zet : Symbol(Zet, Decl(templateTagOnConstructorFunctions.js, 0, 0)) + +z.t = 2 +>z.t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10)) +>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 18, 3)) +>t : Symbol(Zet.t, Decl(templateTagOnConstructorFunctions.js, 7, 10)) + +z.u = false +>z.u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37)) +>z : Symbol(z, Decl(templateTagOnConstructorFunctions.js, 18, 3)) +>u : Symbol(Zet.u, Decl(templateTagOnConstructorFunctions.js, 5, 17), Decl(templateTagOnConstructorFunctions.js, 14, 37)) + diff --git a/tests/baselines/reference/jsdocTemplateConstructorFunction.types b/tests/baselines/reference/jsdocTemplateConstructorFunction.types new file mode 100644 index 00000000000..f838534aa33 --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateConstructorFunction.types @@ -0,0 +1,76 @@ +=== tests/cases/conformance/jsdoc/templateTagOnConstructorFunctions.js === +/** + * @template {T} + * @typedef {(t: T) => T} Id + * @param {T} t + */ +function Zet(t) { +>Zet : typeof Zet +>t : T + + /** @type {T} */ + this.u +>this.u : any +>this : any +>u : any + + this.t = t +>this.t = t : T +>this.t : any +>this : any +>t : any +>t : T +} +/** + * @param {T} v + * @param {Id} id + */ +Zet.prototype.add = function(v, id) { +>Zet.prototype.add = function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: (t: T) => T) => T +>Zet.prototype.add : any +>Zet.prototype : any +>Zet : typeof Zet +>prototype : any +>add : any +>function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: (t: T) => T) => T +>v : T +>id : (t: T) => T + + this.u = v || this.t +>this.u = v || this.t : T +>this.u : T +>this : Zet +>u : T +>v || this.t : T +>v : T +>this.t : T +>this : Zet +>t : T + + return id(this.u) +>id(this.u) : T +>id : (t: T) => T +>this.u : T +>this : Zet +>u : T +} +var z = new Zet(1) +>z : typeof Zet +>new Zet(1) : typeof Zet +>Zet : typeof Zet +>1 : 1 + +z.t = 2 +>z.t = 2 : 2 +>z.t : number +>z : typeof Zet +>t : number +>2 : 2 + +z.u = false +>z.u = false : false +>z.u : number +>z : typeof Zet +>u : number +>false : false + diff --git a/tests/cases/conformance/jsdoc/jsdocTemplateClass.ts b/tests/cases/conformance/jsdoc/jsdocTemplateClass.ts new file mode 100644 index 00000000000..5cd0cde89be --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocTemplateClass.ts @@ -0,0 +1,29 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @Filename: templateTagOnClasses.js + +/** + * @template {T} + * @typedef {(t: T) => T} Id + */ +class Foo { + /** @typedef {(t: T) => T} Id2 */ + /** @param {T} x */ + constructor (x) { + this.a = x + } + /** + * + * @param {T} x + * @param {Id} y + * @param {Id2} alpha + * @return {T} + */ + foo(x, y, alpha) { + return alpha(y(x)) + } +} +var f = new Foo(1) +var g = new Foo(false) +f.a = g.a diff --git a/tests/cases/conformance/jsdoc/jsdocTemplateConstructorFunction.ts b/tests/cases/conformance/jsdoc/jsdocTemplateConstructorFunction.ts new file mode 100644 index 00000000000..dc44afe040a --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocTemplateConstructorFunction.ts @@ -0,0 +1,26 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @Filename: templateTagOnConstructorFunctions.js + +/** + * @template {T} + * @typedef {(t: T) => T} Id + * @param {T} t + */ +function Zet(t) { + /** @type {T} */ + this.u + this.t = t +} +/** + * @param {T} v + * @param {Id} id + */ +Zet.prototype.add = function(v, id) { + this.u = v || this.t + return id(this.u) +} +var z = new Zet(1) +z.t = 2 +z.u = false diff --git a/tests/cases/fourslash/findAllRefsJsDocTemplateTag_class_js.ts b/tests/cases/fourslash/findAllRefsJsDocTemplateTag_class_js.ts index 6577cfce15d..8ec2e86fadb 100644 --- a/tests/cases/fourslash/findAllRefsJsDocTemplateTag_class_js.ts +++ b/tests/cases/fourslash/findAllRefsJsDocTemplateTag_class_js.ts @@ -3,15 +3,14 @@ // @allowJs: true // @Filename: /a.js -// TODO: https://github.com/Microsoft/TypeScript/issues/16411 // Both uses of T should be referenced. /////** @template [|{| "isWriteAccess": true, "isDefinition": true |}T|] */ ////class C { //// constructor() { -//// /** @type {T} */ +//// /** @type {[|T|]} */ //// this.x = null; //// } ////} -verify.singleReferenceGroup("(type parameter) T in C"); +verify.singleReferenceGroup("(type parameter) T in C", test.ranges());