diff --git a/src/server/session.ts b/src/server/session.ts index 7e6bca66c04..12d3ba47476 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -689,7 +689,7 @@ namespace ts.server { this.logErrorWorker(err, cmd); } - private logErrorWorker(err: Error, cmd: string, fileRequest?: protocol.FileRequestArgs): void { + private logErrorWorker(err: Error & PossibleProgramFileInfo, cmd: string, fileRequest?: protocol.FileRequestArgs): void { let msg = "Exception on executing command " + cmd; if (err.message) { msg += ":\n" + indent(err.message); @@ -711,7 +711,9 @@ namespace ts.server { catch { } // tslint:disable-line no-empty } - if (err.message && err.message.indexOf(`Could not find sourceFile:`) !== -1) { + + if (err.ProgramFiles) { + msg += `\n\nProgram files: {JSON.stringify(error.ProgramFiles}}\n`; msg += `\n\nProjects::\n`; let counter = 0; const addProjectInfo = (project: Project) => { diff --git a/src/services/services.ts b/src/services/services.ts index 42b3ac3b31d..93145e01223 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1158,7 +1158,13 @@ namespace ts { function getValidSourceFile(fileName: string): SourceFile { const sourceFile = program.getSourceFile(fileName); if (!sourceFile) { - throw new Error(`Could not find sourceFile: '${fileName}' in ${program && JSON.stringify(program.getSourceFiles().map(f => f.fileName))}.`); + const error: Error & PossibleProgramFileInfo = new Error(`Could not find sourceFile: '${fileName}'.`); + + // We've been having trouble debugging this, so attach sidecar data for the tsserver log. + // See https://github.com/microsoft/TypeScript/issues/30180. + error.ProgramFiles = program.getSourceFiles().map(f => f.fileName); + + throw error; } return sourceFile; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 852d22106a2..2e6e6875a81 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -967,6 +967,11 @@ namespace ts { readonly called: Identifier; readonly nTypeArguments: number; } + + export interface PossibleProgramFileInfo { + ProgramFiles?: string[]; + } + // Get info for an expression like `f <` that may be the start of type arguments. export function getPossibleTypeArgumentsInfo(tokenIn: Node, sourceFile: SourceFile): PossibleTypeArgumentInfo | undefined { let token: Node | undefined = tokenIn; diff --git a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts index 688c8c49ebe..468ad351552 100644 --- a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts +++ b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts @@ -139,7 +139,7 @@ namespace ts.projectSystem { assert.isTrue(false, `should not find file '${imported.path}'`); } catch (e) { - assert.isTrue(e.message.indexOf(`Could not find sourceFile: '${imported.path}' in ["${root.path}"].`) === 0, `Actual: ${e.message}`); + assert.isTrue(e.message.indexOf(`Could not find sourceFile: '${imported.path}'.`) === 0, `Actual: ${e.message}`); } const f2Lookups = getLocationsForModuleLookup("f2"); callsTrackingHost.verifyCalledOnEachEntryNTimes(CalledMapsWithSingleArg.fileExists, f2Lookups, 1);