diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index 415511f01edc7..81566df79325f 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -112,6 +112,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient private firstStart: number; private lastStart: number; private numberRestarts: number; + private cancellationPipeName: string | null = null; private requestQueue: RequestItem[]; private pendingResponses: number; @@ -453,6 +454,10 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient if (this.apiVersion.has208Features()) { args.push('--enableTelemetry'); } + if (this.apiVersion.has220Features()) { + this.cancellationPipeName = electron.getPipeName(`tscancellation-${electron.makeRandomHexString(20)}`); + args.push('--cancellationPipeName', this.cancellationPipeName + '*'); + } electron.fork(modulePath, args, options, (err: any, childProcess: cp.ChildProcess) => { if (err) { this.lastError = err; @@ -795,6 +800,19 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient return true; } } + + if (this.apiVersion.has220Features() && this.cancellationPipeName) { + if (this.trace !== Trace.Off) { + this.logTrace(`TypeScript Service: trying to cancel ongoing request with sequence number ${seq}`); + } + try { + fs.writeFileSync(this.cancellationPipeName + seq, ''); + return true; + } catch (e) { + // noop + } + } + if (this.trace !== Trace.Off) { this.logTrace(`TypeScript Service: tried to cancel request with sequence number ${seq}. But request got already delivered.`); } diff --git a/extensions/typescript/src/utils/electron.ts b/extensions/typescript/src/utils/electron.ts index 916fe4faa61e4..799628d28014c 100644 --- a/extensions/typescript/src/utils/electron.ts +++ b/extensions/typescript/src/utils/electron.ts @@ -17,7 +17,7 @@ export interface IForkOptions { execArgv?: string[]; } -function makeRandomHexString(length: number): string { +export function makeRandomHexString(length: number): string { let chars = ['0', '1', '2', '3', '4', '5', '6', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; let result = ''; for (let i = 0; i < length; i++) { @@ -28,15 +28,20 @@ function makeRandomHexString(length: number): string { } function generatePipeName(): string { - var randomName = 'vscode-' + makeRandomHexString(40); + return getPipeName(makeRandomHexString(40)); +} + +export function getPipeName(name: string): string { + const fullName = 'vscode-' + name; if (process.platform === 'win32') { - return '\\\\.\\pipe\\' + randomName + '-sock'; + return '\\\\.\\pipe\\' + fullName + '-sock'; } // Mac/Unix: use socket file - return path.join(os.tmpdir(), randomName + '.sock'); + return path.join(os.tmpdir(), fullName + '.sock'); } + function generatePatchedEnv(env: any, stdInPipeName: string, stdOutPipeName: string, stdErrPipeName: string): any { // Set the two unique pipe names and the electron flag as process env