diff --git a/src/vs/workbench/api/browser/mainThreadDebugService.ts b/src/vs/workbench/api/browser/mainThreadDebugService.ts index 721187994a6ac8be8c3c7038b2bd1bb21dd74a1e..fcdfb0e41788895cf6c2f2d10f109a58cbd3e7b0 100644 --- a/src/vs/workbench/api/browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/browser/mainThreadDebugService.ts @@ -361,23 +361,24 @@ class ExtensionHostDebugAdapter extends AbstractDebugAdapter { super(); } - public fireError(handle: number, err: Error) { + fireError(handle: number, err: Error) { this._onError.fire(err); } - public fireExit(handle: number, code: number, signal: string) { + fireExit(handle: number, code: number, signal: string) { this._onExit.fire(code); } - public startSession(): Promise { + startSession(): Promise { return Promise.resolve(this._proxy.$startDASession(this._handle, this._ds.getSessionDto(this._session))); } - public sendMessage(message: DebugProtocol.ProtocolMessage): void { + sendMessage(message: DebugProtocol.ProtocolMessage): void { this._proxy.$sendDAMessage(this._handle, convertToDAPaths(message, true)); } - public stopSession(): Promise { + async stopSession(): Promise { + await this.cancelPendingRequests(); return Promise.resolve(this._proxy.$stopDASession(this._handle)); } } diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 3a3add8c50229bdf14d2e51184f175b56536d971..42da79e250d52f5cb9585c3959825ca9b31e99f9 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -33,6 +33,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { variableSetEmitter } from 'vs/workbench/contrib/debug/browser/variablesView'; +import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; export class DebugSession implements IDebugSession { @@ -43,6 +44,7 @@ export class DebugSession implements IDebugSession { private sources = new Map(); private threads = new Map(); + private cancellationMap = new Map(); private rawListeners: IDisposable[] = []; private fetchThreadsScheduler: RunOnceScheduler | undefined; private repl: ReplModel; @@ -235,6 +237,7 @@ export class DebugSession implements IDebugSession { */ terminate(restart = false): Promise { if (this.raw) { + this.cancelAllRequests(); if (this.raw.capabilities.supportsTerminateRequest && this._configuration.resolved.request === 'launch') { return this.raw.terminate(restart).then(response => { return undefined; @@ -252,6 +255,7 @@ export class DebugSession implements IDebugSession { */ disconnect(restart = false): Promise { if (this.raw) { + this.cancelAllRequests(); return this.raw.disconnect(restart).then(response => { return undefined; }); @@ -264,6 +268,7 @@ export class DebugSession implements IDebugSession { */ restart(): Promise { if (this.raw) { + this.cancelAllRequests(); return this.raw.restart().then(() => undefined); } return Promise.reject(new Error('no debug adapter')); @@ -380,7 +385,8 @@ export class DebugSession implements IDebugSession { stackTrace(threadId: number, startFrame: number, levels: number): Promise { if (this.raw) { - return this.raw.stackTrace({ threadId, startFrame, levels }); + const token = this.getNewCancellationToken(threadId); + return this.raw.stackTrace({ threadId, startFrame, levels }, token); } return Promise.reject(new Error('no debug adapter')); } @@ -402,16 +408,18 @@ export class DebugSession implements IDebugSession { return Promise.reject(new Error('no debug adapter')); } - scopes(frameId: number): Promise { + scopes(frameId: number, threadId: number): Promise { if (this.raw) { - return this.raw.scopes({ frameId }); + const token = this.getNewCancellationToken(threadId); + return this.raw.scopes({ frameId }, token); } return Promise.reject(new Error('no debug adapter')); } - variables(variablesReference: number, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise { + variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise { if (this.raw) { - return this.raw.variables({ variablesReference, filter, start, count }); + const token = threadId ? this.getNewCancellationToken(threadId) : undefined; + return this.raw.variables({ variablesReference, filter, start, count }, token); } return Promise.reject(new Error('no debug adapter')); } @@ -541,14 +549,14 @@ export class DebugSession implements IDebugSession { return Promise.reject(new Error('no debug adapter')); } - completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number): Promise { + completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise { if (this.raw) { return this.raw.completions({ frameId, text, column: position.column, - line: position.lineNumber - }).then(response => { + line: position.lineNumber, + }, token).then(response => { const result: CompletionItem[] = []; if (response && response.body && response.body.targets) { @@ -757,6 +765,16 @@ export class DebugSession implements IDebugSession { this.rawListeners.push(this.raw.onDidContinued(event => { const threadId = event.body.allThreadsContinued !== false ? undefined : event.body.threadId; + if (threadId) { + const tokens = this.cancellationMap.get(threadId); + this.cancellationMap.delete(threadId); + if (tokens) { + tokens.forEach(t => t.cancel()); + } + } else { + this.cancelAllRequests(); + } + this.model.clearThreads(this.getId(), false, threadId); this._onDidChangeState.fire(); })); @@ -787,7 +805,7 @@ export class DebugSession implements IDebugSession { source: this.getSource(event.body.source) } : undefined; if (event.body.variablesReference) { - const container = new ExpressionContainer(this, event.body.variablesReference, generateUuid()); + const container = new ExpressionContainer(this, undefined, event.body.variablesReference, generateUuid()); outpuPromises.push(container.getChildren().then(children => { return Promise.all(waitFor).then(() => children.forEach(child => { // Since we can not display multiple trees in a row, we are displaying these variables one after the other (ignoring their names) @@ -896,6 +914,20 @@ export class DebugSession implements IDebugSession { return source; } + private getNewCancellationToken(threadId: number): CancellationToken { + const tokenSource = new CancellationTokenSource(); + const tokens = this.cancellationMap.get(threadId) || []; + tokens.push(tokenSource); + this.cancellationMap.set(threadId, tokens); + + return tokenSource.token; + } + + private cancelAllRequests(): void { + this.cancellationMap.forEach(tokens => tokens.forEach(t => t.cancel())); + this.cancellationMap.clear(); + } + private getUriKey(uri: URI): string { // TODO: the following code does not make sense if uri originates from a different platform return platform.isLinux ? uri.toString() : uri.toString().toLowerCase(); diff --git a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts index 28e19bf76684f4bc91ca1c764c8ac1f28078faaa..2e8ce0cf55e5f453011c882899529f3990906427 100644 --- a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts @@ -19,6 +19,7 @@ import { IProcessEnvironment } from 'vs/base/common/platform'; import { env as processEnv } from 'vs/base/common/process'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { CancellationToken } from 'vs/base/common/cancellation'; /** * This interface represents a single command line argument split into a "prefix" and a "path" half. @@ -112,8 +113,6 @@ export class RawDebugSession implements IDisposable { } })); - this.toDispose.push(this.onDidContinued(() => this.cancelPendingRequests())); - this.debugAdapter.onEvent(event => { switch (event.event) { case 'initialized': @@ -346,9 +345,9 @@ export class RawDebugSession implements IDisposable { return Promise.reject(new Error('restartFrame not supported')); } - completions(args: DebugProtocol.CompletionsArguments): Promise { + completions(args: DebugProtocol.CompletionsArguments, token: CancellationToken): Promise { if (this.capabilities.supportsCompletionsRequest) { - return this.send('completions', args); + return this.send('completions', args, token); } return Promise.reject(new Error('completions not supported')); } @@ -389,8 +388,8 @@ export class RawDebugSession implements IDisposable { return Promise.reject(new Error('configurationDone not supported')); } - stackTrace(args: DebugProtocol.StackTraceArguments): Promise { - return this.send('stackTrace', args); + stackTrace(args: DebugProtocol.StackTraceArguments, token: CancellationToken): Promise { + return this.send('stackTrace', args, token); } exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): Promise { @@ -400,12 +399,12 @@ export class RawDebugSession implements IDisposable { return Promise.reject(new Error('exceptionInfo not supported')); } - scopes(args: DebugProtocol.ScopesArguments): Promise { - return this.send('scopes', args); + scopes(args: DebugProtocol.ScopesArguments, token: CancellationToken): Promise { + return this.send('scopes', args, token); } - variables(args: DebugProtocol.VariablesArguments): Promise { - return this.send('variables', args); + variables(args: DebugProtocol.VariablesArguments, token?: CancellationToken): Promise { + return this.send('variables', args, token); } source(args: DebugProtocol.SourceArguments): Promise { @@ -482,7 +481,7 @@ export class RawDebugSession implements IDisposable { if (!this.inShutdown) { this.inShutdown = true; if (this.debugAdapter) { - return this.send('disconnect', { restart }, 500).then(() => { + return this.send('disconnect', { restart }, undefined, 500).then(() => { this.stopAdapter(error); }, () => { // ignore error @@ -494,23 +493,10 @@ export class RawDebugSession implements IDisposable { return Promise.resolve(undefined); } - private cancelPendingRequests(): void { - if (this.debugAdapter) { - if (this.capabilities.supportsCancelRequest) { - this.debugAdapter.getPendingRequestIds().forEach(requestId => { - this.cancel({ requestId }); - }); - } else { - this.debugAdapter.cancelPendingRequests(); - } - } - } - private stopAdapter(error?: Error): Promise { if (this.debugAdapter) { const da = this.debugAdapter; this.debugAdapter = null; - this.cancelPendingRequests(); return da.stopSession().then(_ => { this.debugAdapterStopped = true; this.fireAdapterExitEvent(error); @@ -642,20 +628,34 @@ export class RawDebugSession implements IDisposable { return this.windowsService.openExtensionDevelopmentHostWindow(args, env); } - private send(command: string, args: any, timeout?: number): Promise { + private send(command: string, args: any, token?: CancellationToken, timeout?: number): Promise { return new Promise((completeDispatch, errorDispatch) => { if (!this.debugAdapter) { errorDispatch(new Error('no debug adapter found')); return; } - this.debugAdapter.sendRequest(command, args, (response: R) => { + let cancelationListener: IDisposable; + const requestId = this.debugAdapter.sendRequest(command, args, (response: R) => { + if (cancelationListener) { + cancelationListener.dispose(); + } + if (response.success) { completeDispatch(response); } else { errorDispatch(response); } }, timeout); - }).then(response => response, err => Promise.reject(this.handleErrorResponse(err))); + + if (token) { + cancelationListener = token.onCancellationRequested(() => { + cancelationListener.dispose(); + if (this.capabilities.supportsCancelRequest) { + this.cancel({ requestId }); + } + }); + } + }).then(undefined, err => Promise.reject(this.handleErrorResponse(err))); } private handleErrorResponse(errorResponse: DebugProtocol.Response): Error { diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 3b32a852e44f0ead40ea28983164eefaec3010d8..ba438198881b1484b5838b03fcf135b5912ba87e 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -149,7 +149,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati const text = model.getLineContent(position.lineNumber); const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame; const frameId = focusedStackFrame ? focusedStackFrame.frameId : undefined; - const suggestions = await session.completions(frameId, text, position, overwriteBefore); + const suggestions = await session.completions(frameId, text, position, overwriteBefore, token); return { suggestions }; } diff --git a/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts b/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts index f288628f314314644dcf749015f204e90e7c67b2..56a9de64e264d1a7fd06058cfbb59e4b695f2ab3 100644 --- a/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts +++ b/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts @@ -71,7 +71,7 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter { } } - sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void { + sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): number { const request: any = { command: command }; @@ -101,6 +101,8 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter { // store callback for this request this.pendingRequests.set(request.seq, clb); } + + return request.seq; } acceptMessage(message: DebugProtocol.ProtocolMessage): void { @@ -137,7 +139,11 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter { this.sendMessage(message); } - async cancelPendingRequests(): Promise { + protected async cancelPendingRequests(): Promise { + if (this.pendingRequests.size === 0) { + return Promise.resolve(); + } + const pending = new Map void>(); this.pendingRequests.forEach((value, key) => pending.set(key, value)); await timeout(500); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 7900963c47c962c529a68d2f52084eba79ae519b..8f09afa61651745d8dd445696f606b81653aee43 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -210,8 +210,8 @@ export interface IDebugSession extends ITreeElement { stackTrace(threadId: number, startFrame: number, levels: number): Promise; exceptionInfo(threadId: number): Promise; - scopes(frameId: number): Promise; - variables(variablesReference: number, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise; + scopes(frameId: number, threadId: number): Promise; + variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise; evaluate(expression: string, frameId?: number, context?: string): Promise; customRequest(request: string, args: any): Promise; @@ -225,7 +225,7 @@ export interface IDebugSession extends ITreeElement { pause(threadId: number): Promise; terminateThreads(threadIds: number[]): Promise; - completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number): Promise; + completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise; setVariable(variablesReference: number | undefined, name: string, value: string): Promise; loadSource(resource: uri): Promise; getLoadedSources(): Promise; @@ -504,10 +504,8 @@ export interface IDebugAdapter extends IDisposable { startSession(): Promise; sendMessage(message: DebugProtocol.ProtocolMessage): void; sendResponse(response: DebugProtocol.Response): void; - sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void; + sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): number; stopSession(): Promise; - cancelPendingRequests(): void; - getPendingRequestIds(): number[]; } export interface IDebugAdapterFactory extends ITerminalLauncher { diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index 8adaccd5b0ff479f458bd8cd366edf8e2d5716e3..c0830fb7e60473ec252707e5a73764b1aa267c9e 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -37,6 +37,7 @@ export class ExpressionContainer implements IExpressionContainer { constructor( protected session: IDebugSession | undefined, + protected threadId: number | undefined, private _reference: number | undefined, private id: string, public namedVariables: number | undefined = 0, @@ -85,7 +86,7 @@ export class ExpressionContainer implements IExpressionContainer { for (let i = 0; i < numberOfChunks; i++) { const start = (this.startOfVariables || 0) + i * chunkSize; const count = Math.min(chunkSize, this.indexedVariables - i * chunkSize); - children.push(new Variable(this.session, this, this.reference, `[${start}..${start + count - 1}]`, '', '', undefined, count, { kind: 'virtual' }, undefined, true, start)); + children.push(new Variable(this.session, this.threadId, this, this.reference, `[${start}..${start + count - 1}]`, '', '', undefined, count, { kind: 'virtual' }, undefined, true, start)); } return children; @@ -109,12 +110,12 @@ export class ExpressionContainer implements IExpressionContainer { } private fetchVariables(start: number | undefined, count: number | undefined, filter: 'indexed' | 'named' | undefined): Promise { - return this.session!.variables(this.reference || 0, filter, start, count).then(response => { + return this.session!.variables(this.reference || 0, this.threadId, filter, start, count).then(response => { return response && response.body && response.body.variables ? distinct(response.body.variables.filter(v => !!v && isString(v.name)), (v: DebugProtocol.Variable) => v.name).map((v: DebugProtocol.Variable) => - new Variable(this.session, this, v.variablesReference, v.name, v.evaluateName, v.value, v.namedVariables, v.indexedVariables, v.presentationHint, v.type)) + new Variable(this.session, this.threadId, this, v.variablesReference, v.name, v.evaluateName, v.value, v.namedVariables, v.indexedVariables, v.presentationHint, v.type)) : []; - }, (e: Error) => [new Variable(this.session, this, 0, e.message, e.message, '', 0, 0, { kind: 'virtual' }, undefined, false)]); + }, (e: Error) => [new Variable(this.session, this.threadId, this, 0, e.message, e.message, '', 0, 0, { kind: 'virtual' }, undefined, false)]); } // The adapter explicitly sents the children count of an expression only if there are lots of children which should be chunked. @@ -171,7 +172,7 @@ export class Expression extends ExpressionContainer implements IExpression { public available: boolean; constructor(public name: string, id = generateUuid()) { - super(undefined, 0, id); + super(undefined, undefined, 0, id); this.available = false; // name is not set if the expression is just being added // in that case do not set default value to prevent flashing #14499 @@ -196,6 +197,7 @@ export class Variable extends ExpressionContainer implements IExpression { constructor( session: IDebugSession | undefined, + threadId: number | undefined, public parent: IExpressionContainer, reference: number | undefined, public name: string, @@ -208,7 +210,7 @@ export class Variable extends ExpressionContainer implements IExpression { public available = true, startOfVariables = 0 ) { - super(session, reference, `variable:${parent.getId()}:${name}`, namedVariables, indexedVariables, startOfVariables); + super(session, threadId, reference, `variable:${parent.getId()}:${name}`, namedVariables, indexedVariables, startOfVariables); this.value = value || ''; } @@ -248,7 +250,7 @@ export class Scope extends ExpressionContainer implements IScope { indexedVariables?: number, public range?: IRange ) { - super(stackFrame.thread.session, reference, `scope:${name}:${index}`, namedVariables, indexedVariables); + super(stackFrame.thread.session, stackFrame.thread.threadId, reference, `scope:${name}:${index}`, namedVariables, indexedVariables); } toString(): string { @@ -276,7 +278,7 @@ export class StackFrame implements IStackFrame { getScopes(): Promise { if (!this.scopes) { - this.scopes = this.thread.session.scopes(this.frameId).then(response => { + this.scopes = this.thread.session.scopes(this.frameId, this.thread.threadId).then(response => { return response && response.body && response.body.scopes ? response.body.scopes.map((rs, index) => new Scope(this, index, rs.name, rs.variablesReference, rs.expensive, rs.namedVariables, rs.indexedVariables, rs.line && rs.column && rs.endLine && rs.endColumn ? new Range(rs.line, rs.column, rs.endLine, rs.endColumn) : undefined)) : []; diff --git a/src/vs/workbench/contrib/debug/common/replModel.ts b/src/vs/workbench/contrib/debug/common/replModel.ts index 4d60ecea55a51255322e1a0ce2dc1911eda67944..7808f9e6a0d7838da14734c8a1e898af1b8db281 100644 --- a/src/vs/workbench/contrib/debug/common/replModel.ts +++ b/src/vs/workbench/contrib/debug/common/replModel.ts @@ -97,7 +97,7 @@ export class ReplEvaluationInput implements IReplElement { export class ReplEvaluationResult extends ExpressionContainer implements IReplElement { constructor() { - super(undefined, 0, generateUuid()); + super(undefined, undefined, 0, generateUuid()); } toString(): string { diff --git a/src/vs/workbench/contrib/debug/node/debugAdapter.ts b/src/vs/workbench/contrib/debug/node/debugAdapter.ts index c13409c0603ecbc05d9550b1305ec0c4642a1cfd..84ec75a9c842cee6e16d6ef8cb17e1afca865285 100644 --- a/src/vs/workbench/contrib/debug/node/debugAdapter.ts +++ b/src/vs/workbench/contrib/debug/node/debugAdapter.ts @@ -127,8 +127,8 @@ export class SocketDebugAdapter extends StreamDebugAdapter { }); } - stopSession(): Promise { - + async stopSession(): Promise { + await this.cancelPendingRequests(); if (this.socket) { this.socket.end(); this.socket = undefined; @@ -249,7 +249,7 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter { } } - stopSession(): Promise { + async stopSession(): Promise { if (!this.serverProcess) { return Promise.resolve(undefined); @@ -258,6 +258,7 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter { // when killing a process in windows its child // processes are *not* killed but become root // processes. Therefore we use TASKKILL.EXE + await this.cancelPendingRequests(); if (platform.isWindows) { return new Promise((c, e) => { const killer = cp.exec(`taskkill /F /T /PID ${this.serverProcess!.pid}`, function (err, stdout, stderr) { diff --git a/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts b/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts index dd89032131988333dbfff04c44aa7f35db686b73..48e2c89f0bc2d9c1ae2d16fc7cf3e653e943c449 100644 --- a/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts @@ -76,7 +76,7 @@ suite('Debug - Base Debug View', () => { const stackFrame = new StackFrame(thread, 1, null!, 'app.js', 'normal', { startLineNumber: 1, startColumn: 1, endLineNumber: undefined!, endColumn: undefined! }, 0); const scope = new Scope(stackFrame, 1, 'local', 1, false, 10, 10); - let variable = new Variable(session, scope, 2, 'foo', 'bar.foo', undefined!, 0, 0, {}, 'string'); + let variable = new Variable(session, 1, scope, 2, 'foo', 'bar.foo', undefined!, 0, 0, {}, 'string'); let expression = $('.'); let name = $('.'); let value = $('.'); @@ -104,7 +104,7 @@ suite('Debug - Base Debug View', () => { assert.ok(value.querySelector('a')); assert.equal(value.querySelector('a')!.textContent, variable.value); - variable = new Variable(session, scope, 2, 'console', 'console', '5', 0, 0, { kind: 'virtual' }); + variable = new Variable(session, 1, scope, 2, 'console', 'console', '5', 0, 0, { kind: 'virtual' }); expression = $('.'); name = $('.'); value = $('.'); diff --git a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts index f70b8aee729120aa595862f3d0efc70afca0c6ff..0abec14fb2100151d3fdb525b654ec42a32b37cb 100644 --- a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts @@ -264,7 +264,7 @@ export class MockSession implements IDebugSession { scopes(frameId: number): Promise { throw new Error('Method not implemented.'); } - variables(variablesReference: number, filter: 'indexed' | 'named', start: number, count: number): Promise { + variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named', start: number, count: number): Promise { throw new Error('Method not implemented.'); } evaluate(expression: string, frameId: number, context?: string): Promise {