提交 460ef3a4 编写于 作者: I isidor

debug session: more async await

上级 7485ffde
......@@ -30,7 +30,6 @@ import { Range } from 'vs/editor/common/core/range';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
import { onUnexpectedError } from 'vs/base/common/errors';
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';
......@@ -181,110 +180,100 @@ export class DebugSession implements IDebugSession {
/**
* create and initialize a new debug adapter for this session
*/
initialize(dbgr: IDebugger): Promise<void> {
async initialize(dbgr: IDebugger): Promise<void> {
if (this.raw) {
// if there was already a connection make sure to remove old listeners
this.shutdown();
}
return dbgr.getCustomTelemetryService().then(customTelemetryService => {
return dbgr.createDebugAdapter(this).then(debugAdapter => {
this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.extensionHostDebugService, this.openerService);
return this.raw.start().then(() => {
this.registerListeners();
return this.raw!.initialize({
clientID: 'vscode',
clientName: this.productService.nameLong,
adapterID: this.configuration.type,
pathFormat: 'path',
linesStartAt1: true,
columnsStartAt1: true,
supportsVariableType: true, // #8858
supportsVariablePaging: true, // #9537
supportsRunInTerminalRequest: true, // #10574
locale: platform.locale
}).then(() => {
this.initialized = true;
this._onDidChangeState.fire();
this.model.setExceptionBreakpoints(this.raw!.capabilities.exceptionBreakpointFilters || []);
});
});
try {
const customTelemetryService = await dbgr.getCustomTelemetryService();
const debugAdapter = await dbgr.createDebugAdapter(this);
this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.extensionHostDebugService, this.openerService);
await this.raw.start();
this.registerListeners();
await this.raw!.initialize({
clientID: 'vscode',
clientName: this.productService.nameLong,
adapterID: this.configuration.type,
pathFormat: 'path',
linesStartAt1: true,
columnsStartAt1: true,
supportsVariableType: true, // #8858
supportsVariablePaging: true, // #9537
supportsRunInTerminalRequest: true, // #10574
locale: platform.locale
});
}).then(undefined, err => {
this.initialized = true;
this._onDidChangeState.fire();
return Promise.reject(err);
});
this.model.setExceptionBreakpoints(this.raw!.capabilities.exceptionBreakpointFilters || []);
} catch (err) {
this.initialized = true;
this._onDidChangeState.fire();
throw err;
}
}
/**
* launch or attach to the debuggee
*/
launchOrAttach(config: IConfig): Promise<void> {
if (this.raw) {
async launchOrAttach(config: IConfig): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
// __sessionID only used for EH debugging (but we add it always for now...)
config.__sessionId = this.getId();
// __sessionID only used for EH debugging (but we add it always for now...)
config.__sessionId = this.getId();
await this.raw.launchOrAttach(config);
return this.raw.launchOrAttach(config).then(result => {
return undefined;
});
}
return Promise.reject(new Error('no debug adapter'));
}
/**
* end the current debug adapter session
*/
terminate(restart = false): Promise<void> {
if (this.raw) {
this.cancelAllRequests();
if (this.raw.capabilities.supportsTerminateRequest && this._configuration.resolved.request === 'launch') {
return this.raw.terminate(restart).then(response => {
return undefined;
});
}
return this.raw.disconnect(restart).then(response => {
return undefined;
});
async terminate(restart = false): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
this.cancelAllRequests();
if (this.raw.capabilities.supportsTerminateRequest && this._configuration.resolved.request === 'launch') {
await this.raw.terminate(restart);
} else {
await this.raw.disconnect(restart);
}
return Promise.reject(new Error('no debug adapter'));
}
/**
* end the current debug adapter session
*/
disconnect(restart = false): Promise<void> {
if (this.raw) {
this.cancelAllRequests();
return this.raw.disconnect(restart).then(response => {
return undefined;
});
async disconnect(restart = false): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
this.cancelAllRequests();
await this.raw.disconnect(restart);
}
/**
* restart debug adapter session
*/
restart(): Promise<void> {
if (this.raw) {
this.cancelAllRequests();
return this.raw.restart().then(() => undefined);
async restart(): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
}
sendBreakpoints(modelUri: URI, breakpointsToSend: IBreakpoint[], sourceModified: boolean): Promise<void> {
this.cancelAllRequests();
await this.raw.restart();
}
async sendBreakpoints(modelUri: URI, breakpointsToSend: IBreakpoint[], sourceModified: boolean): Promise<void> {
if (!this.raw) {
return Promise.reject(new Error('no debug adapter'));
throw new Error('no debug adapter');
}
if (!this.raw.readyForBreakpoints) {
......@@ -300,237 +289,252 @@ export class DebugSession implements IDebugSession {
rawSource.path = normalizeDriveLetter(rawSource.path);
}
return this.raw.setBreakpoints({
const response = await this.raw.setBreakpoints({
source: rawSource,
lines: breakpointsToSend.map(bp => bp.sessionAgnosticData.lineNumber),
breakpoints: breakpointsToSend.map(bp => ({ line: bp.sessionAgnosticData.lineNumber, column: bp.sessionAgnosticData.column, condition: bp.condition, hitCondition: bp.hitCondition, logMessage: bp.logMessage })),
sourceModified
}).then(response => {
});
if (response && response.body) {
const data = new Map<string, DebugProtocol.Breakpoint>();
for (let i = 0; i < breakpointsToSend.length; i++) {
data.set(breakpointsToSend[i].getId(), response.body.breakpoints[i]);
}
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
}
}
async sendFunctionBreakpoints(fbpts: IFunctionBreakpoint[]): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
if (this.raw.readyForBreakpoints) {
const response = await this.raw.setFunctionBreakpoints({ breakpoints: fbpts });
if (response && response.body) {
const data = new Map<string, DebugProtocol.Breakpoint>();
for (let i = 0; i < breakpointsToSend.length; i++) {
data.set(breakpointsToSend[i].getId(), response.body.breakpoints[i]);
for (let i = 0; i < fbpts.length; i++) {
data.set(fbpts[i].getId(), response.body.breakpoints[i]);
}
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
}
});
}
}
sendFunctionBreakpoints(fbpts: IFunctionBreakpoint[]): Promise<void> {
if (this.raw) {
if (this.raw.readyForBreakpoints) {
return this.raw.setFunctionBreakpoints({ breakpoints: fbpts }).then(response => {
if (response && response.body) {
const data = new Map<string, DebugProtocol.Breakpoint>();
for (let i = 0; i < fbpts.length; i++) {
data.set(fbpts[i].getId(), response.body.breakpoints[i]);
}
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
}
});
}
return Promise.resolve(undefined);
async sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
if (this.raw.readyForBreakpoints) {
await this.raw.setExceptionBreakpoints({ filters: exbpts.map(exb => exb.filter) });
}
}
sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void> {
if (this.raw) {
if (this.raw.readyForBreakpoints) {
return this.raw.setExceptionBreakpoints({ filters: exbpts.map(exb => exb.filter) }).then(() => undefined);
}
return Promise.resolve(undefined);
async dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
if (!this.raw.readyForBreakpoints) {
throw new Error(nls.localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints"));
}
const response = await this.raw.dataBreakpointInfo({ name, variablesReference });
return response.body;
}
dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }> {
if (this.raw) {
if (this.raw.readyForBreakpoints) {
return this.raw.dataBreakpointInfo({ name, variablesReference }).then(response => response.body);
}
return Promise.reject(new Error(nls.localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints")));
async sendDataBreakpoints(dataBreakpoints: IDataBreakpoint[]): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
}
sendDataBreakpoints(dataBreakpoints: IDataBreakpoint[]): Promise<void> {
if (this.raw) {
if (this.raw.readyForBreakpoints) {
return this.raw.setDataBreakpoints({ breakpoints: dataBreakpoints }).then(response => {
if (response && response.body) {
const data = new Map<string, DebugProtocol.Breakpoint>();
for (let i = 0; i < dataBreakpoints.length; i++) {
data.set(dataBreakpoints[i].getId(), response.body.breakpoints[i]);
}
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
}
});
if (this.raw.readyForBreakpoints) {
const response = await this.raw.setDataBreakpoints({ breakpoints: dataBreakpoints });
if (response && response.body) {
const data = new Map<string, DebugProtocol.Breakpoint>();
for (let i = 0; i < dataBreakpoints.length; i++) {
data.set(dataBreakpoints[i].getId(), response.body.breakpoints[i]);
}
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
}
return Promise.resolve(undefined);
}
return Promise.reject(new Error('no debug adapter'));
}
async breakpointsLocations(uri: URI, lineNumber: number): Promise<IPosition[]> {
if (this.raw) {
const source = this.getRawSource(uri);
const response = await this.raw.breakpointLocations({ source, line: lineNumber });
if (!response.body || !response.body.breakpoints) {
return [];
}
const positions = response.body.breakpoints.map(bp => ({ lineNumber: bp.line, column: bp.column || 1 }));
if (!this.raw) {
throw new Error('no debug adapter');
}
return distinct(positions, p => `${p.lineNumber}:${p.column}`);
const source = this.getRawSource(uri);
const response = await this.raw.breakpointLocations({ source, line: lineNumber });
if (!response.body || !response.body.breakpoints) {
return [];
}
return Promise.reject(new Error('no debug adapter'));
const positions = response.body.breakpoints.map(bp => ({ lineNumber: bp.line, column: bp.column || 1 }));
return distinct(positions, p => `${p.lineNumber}:${p.column}`);
}
customRequest(request: string, args: any): Promise<DebugProtocol.Response> {
if (this.raw) {
return this.raw.custom(request, args);
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
return this.raw.custom(request, args);
}
stackTrace(threadId: number, startFrame: number, levels: number): Promise<DebugProtocol.StackTraceResponse> {
if (this.raw) {
const token = this.getNewCancellationToken(threadId);
return this.raw.stackTrace({ threadId, startFrame, levels }, token);
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
const token = this.getNewCancellationToken(threadId);
return this.raw.stackTrace({ threadId, startFrame, levels }, token);
}
exceptionInfo(threadId: number): Promise<IExceptionInfo | undefined> {
if (this.raw) {
return this.raw.exceptionInfo({ threadId }).then(response => {
if (response) {
return {
id: response.body.exceptionId,
description: response.body.description,
breakMode: response.body.breakMode,
details: response.body.details
};
}
return undefined;
});
async exceptionInfo(threadId: number): Promise<IExceptionInfo | undefined> {
if (!this.raw) {
throw new Error('no debug adapter');
}
const response = await this.raw.exceptionInfo({ threadId });
if (response) {
return {
id: response.body.exceptionId,
description: response.body.description,
breakMode: response.body.breakMode,
details: response.body.details
};
}
return Promise.reject(new Error('no debug adapter'));
return undefined;
}
scopes(frameId: number, threadId: number): Promise<DebugProtocol.ScopesResponse> {
if (this.raw) {
const token = this.getNewCancellationToken(threadId);
return this.raw.scopes({ frameId }, token);
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
const token = this.getNewCancellationToken(threadId);
return this.raw.scopes({ frameId }, token);
}
variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise<DebugProtocol.VariablesResponse> {
if (this.raw) {
const token = threadId ? this.getNewCancellationToken(threadId) : undefined;
return this.raw.variables({ variablesReference, filter, start, count }, token);
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
const token = threadId ? this.getNewCancellationToken(threadId) : undefined;
return this.raw.variables({ variablesReference, filter, start, count }, token);
}
evaluate(expression: string, frameId: number, context?: string): Promise<DebugProtocol.EvaluateResponse> {
if (this.raw) {
return this.raw.evaluate({ expression, frameId, context });
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
return this.raw.evaluate({ expression, frameId, context });
}
restartFrame(frameId: number, threadId: number): Promise<void> {
if (this.raw) {
return this.raw.restartFrame({ frameId }, threadId).then(() => undefined);
async restartFrame(frameId: number, threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.restartFrame({ frameId }, threadId);
}
next(threadId: number): Promise<void> {
if (this.raw) {
return this.raw.next({ threadId }).then(() => undefined);
async next(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.next({ threadId });
}
stepIn(threadId: number): Promise<void> {
if (this.raw) {
return this.raw.stepIn({ threadId }).then(() => undefined);
async stepIn(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.stepIn({ threadId });
}
stepOut(threadId: number): Promise<void> {
if (this.raw) {
return this.raw.stepOut({ threadId }).then(() => undefined);
async stepOut(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.stepOut({ threadId });
}
stepBack(threadId: number): Promise<void> {
if (this.raw) {
return this.raw.stepBack({ threadId }).then(() => undefined);
async stepBack(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.stepBack({ threadId });
}
continue(threadId: number): Promise<void> {
if (this.raw) {
return this.raw.continue({ threadId }).then(() => undefined);
async continue(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.continue({ threadId });
}
reverseContinue(threadId: number): Promise<void> {
if (this.raw) {
return this.raw.reverseContinue({ threadId }).then(() => undefined);
async reverseContinue(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.reverseContinue({ threadId });
}
pause(threadId: number): Promise<void> {
if (this.raw) {
return this.raw.pause({ threadId }).then(() => undefined);
async pause(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.pause({ threadId });
}
terminateThreads(threadIds?: number[]): Promise<void> {
if (this.raw) {
return this.raw.terminateThreads({ threadIds }).then(() => undefined);
async terminateThreads(threadIds?: number[]): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
await this.raw.terminateThreads({ threadIds });
}
setVariable(variablesReference: number, name: string, value: string): Promise<DebugProtocol.SetVariableResponse> {
if (this.raw) {
return this.raw.setVariable({ variablesReference, name, value });
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
return this.raw.setVariable({ variablesReference, name, value });
}
gotoTargets(source: DebugProtocol.Source, line: number, column?: number): Promise<DebugProtocol.GotoTargetsResponse> {
if (this.raw) {
return this.raw.gotoTargets({ source, line, column });
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
return this.raw.gotoTargets({ source, line, column });
}
goto(threadId: number, targetId: number): Promise<DebugProtocol.GotoResponse> {
if (this.raw) {
return this.raw.goto({ threadId, targetId });
if (!this.raw) {
throw new Error('no debug adapter');
}
return Promise.reject(new Error('no debug adapter'));
return this.raw.goto({ threadId, targetId });
}
loadSource(resource: URI): Promise<DebugProtocol.SourceResponse> {
if (!this.raw) {
return Promise.reject(new Error('no debug adapter'));
}
......@@ -548,50 +552,48 @@ export class DebugSession implements IDebugSession {
return this.raw.source({ sourceReference: rawSource.sourceReference || 0, source: rawSource });
}
getLoadedSources(): Promise<Source[]> {
if (this.raw) {
return this.raw.loadedSources({}).then(response => {
if (response.body && response.body.sources) {
return response.body.sources.map(src => this.getSource(src));
} else {
return [];
}
}, () => {
return [];
});
async getLoadedSources(): Promise<Source[]> {
if (!this.raw) {
return Promise.reject(new Error('no debug adapter'));
}
const response = await this.raw.loadedSources({});
if (response.body && response.body.sources) {
return response.body.sources.map(src => this.getSource(src));
} else {
return [];
}
return Promise.reject(new Error('no debug adapter'));
}
completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise<CompletionItem[]> {
if (this.raw) {
return this.raw.completions({
frameId,
text,
column: position.column,
line: position.lineNumber,
}, token).then(response => {
const result: CompletionItem[] = [];
if (response && response.body && response.body.targets) {
response.body.targets.forEach(item => {
if (item && item.label) {
result.push({
label: item.label,
insertText: item.text || item.label,
kind: completionKindFromString(item.type || 'property'),
filterText: (item.start && item.length) ? text.substr(item.start, item.length).concat(item.label) : undefined,
range: Range.fromPositions(position.delta(0, -(item.length || overwriteBefore)), position),
sortText: item.sortText
});
}
async completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise<CompletionItem[]> {
if (!this.raw) {
return Promise.reject(new Error('no debug adapter'));
}
const response = await this.raw.completions({
frameId,
text,
column: position.column,
line: position.lineNumber,
}, token);
const result: CompletionItem[] = [];
if (response && response.body && response.body.targets) {
response.body.targets.forEach(item => {
if (item && item.label) {
result.push({
label: item.label,
insertText: item.text || item.label,
kind: completionKindFromString(item.type || 'property'),
filterText: (item.start && item.length) ? text.substr(item.start, item.length).concat(item.label) : undefined,
range: Range.fromPositions(position.delta(0, -(item.length || overwriteBefore)), position),
sortText: item.sortText
});
}
return result;
});
}
return Promise.reject(new Error('no debug adapter'));
return result;
}
//---- threads
......@@ -676,8 +678,9 @@ export class DebugSession implements IDebugSession {
}
}
private fetchThreads(stoppedDetails?: IRawStoppedDetails): Promise<void> {
return this.raw ? this.raw.threads().then(response => {
private async fetchThreads(stoppedDetails?: IRawStoppedDetails): Promise<void> {
if (this.raw) {
const response = await this.raw.threads();
if (response && response.body && response.body.threads) {
this.model.rawUpdate({
sessionId: this.getId(),
......@@ -685,7 +688,7 @@ export class DebugSession implements IDebugSession {
stoppedDetails
});
}
}) : Promise.resolve(undefined);
}
}
//---- private
......@@ -695,57 +698,64 @@ export class DebugSession implements IDebugSession {
return;
}
this.rawListeners.push(this.raw.onDidInitialize(() => {
this.rawListeners.push(this.raw.onDidInitialize(async () => {
aria.status(nls.localize('debuggingStarted', "Debugging started."));
const sendConfigurationDone = () => {
const sendConfigurationDone = async () => {
if (this.raw && this.raw.capabilities.supportsConfigurationDoneRequest) {
return this.raw.configurationDone().then(undefined, () => {
try {
await this.raw.configurationDone();
} catch (e) {
// Disconnect the debug session on configuration done error #10596
if (this.raw) {
this.raw.disconnect();
}
});
}
}
return undefined;
};
// Send all breakpoints
this.debugService.sendAllBreakpoints(this).then(sendConfigurationDone, sendConfigurationDone)
.then(() => this.fetchThreads());
try {
await this.debugService.sendAllBreakpoints(this);
await sendConfigurationDone();
} catch {
await sendConfigurationDone();
}
await this.fetchThreads();
}));
this.rawListeners.push(this.raw.onDidStop(event => {
this.fetchThreads(event.body).then(() => {
const thread = typeof event.body.threadId === 'number' ? this.getThread(event.body.threadId) : undefined;
if (thread) {
// Call fetch call stack twice, the first only return the top stack frame.
// Second retrieves the rest of the call stack. For performance reasons #25605
const promises = this.model.fetchCallStack(<Thread>thread);
const focus = async () => {
if (!event.body.preserveFocusHint && thread.getCallStack().length) {
await this.debugService.focusStackFrame(undefined, thread);
if (thread.stoppedDetails) {
if (this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak') {
this.viewletService.openViewlet(VIEWLET_ID);
}
if (this.configurationService.getValue<IDebugConfiguration>('debug').focusWindowOnBreak) {
this.hostService.focus();
}
this.rawListeners.push(this.raw.onDidStop(async event => {
await this.fetchThreads(event.body);
const thread = typeof event.body.threadId === 'number' ? this.getThread(event.body.threadId) : undefined;
if (thread) {
// Call fetch call stack twice, the first only return the top stack frame.
// Second retrieves the rest of the call stack. For performance reasons #25605
const promises = this.model.fetchCallStack(<Thread>thread);
const focus = async () => {
if (!event.body.preserveFocusHint && thread.getCallStack().length) {
await this.debugService.focusStackFrame(undefined, thread);
if (thread.stoppedDetails) {
if (this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak') {
this.viewletService.openViewlet(VIEWLET_ID);
}
}
};
promises.topCallStack.then(focus);
promises.wholeCallStack.then(() => {
if (!this.debugService.getViewModel().focusedStackFrame) {
// The top stack frame can be deemphesized so try to focus again #68616
focus();
if (this.configurationService.getValue<IDebugConfiguration>('debug').focusWindowOnBreak) {
this.hostService.focus();
}
}
});
}
};
await promises.topCallStack;
focus();
await promises.wholeCallStack;
if (!this.debugService.getViewModel().focusedStackFrame) {
// The top stack frame can be deemphesized so try to focus again #68616
focus();
}
}).then(() => this._onDidChangeState.fire());
}
this._onDidChangeState.fire();
}));
this.rawListeners.push(this.raw.onDidThread(event => {
......@@ -765,12 +775,12 @@ export class DebugSession implements IDebugSession {
}
}));
this.rawListeners.push(this.raw.onDidTerminateDebugee(event => {
this.rawListeners.push(this.raw.onDidTerminateDebugee(async event => {
aria.status(nls.localize('debuggingStopped', "Debugging stopped."));
if (event.body && event.body.restart) {
this.debugService.restartSession(this, event.body.restart).then(undefined, onUnexpectedError);
await this.debugService.restartSession(this, event.body.restart);
} else if (this.raw) {
this.raw.disconnect();
await this.raw.disconnect();
}
}));
......@@ -791,7 +801,7 @@ export class DebugSession implements IDebugSession {
}));
let outpuPromises: Promise<void>[] = [];
this.rawListeners.push(this.raw.onDidOutput(event => {
this.rawListeners.push(this.raw.onDidOutput(async event => {
if (!event.body || !this.raw) {
return;
}
......@@ -817,17 +827,21 @@ export class DebugSession implements IDebugSession {
} : undefined;
if (event.body.variablesReference) {
const container = new ExpressionContainer(this, undefined, event.body.variablesReference, generateUuid());
outpuPromises.push(container.getChildren().then(children => {
return Promise.all(waitFor).then(() => children.forEach(child => {
outpuPromises.push(container.getChildren().then(async children => {
await Promise.all(waitFor);
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)
(<any>child).name = null;
this.appendToRepl(child, outputSeverity, source);
}));
});
}));
} else if (typeof event.body.output === 'string') {
Promise.all(waitFor).then(() => this.appendToRepl(event.body.output, outputSeverity, source));
await Promise.all(waitFor);
this.appendToRepl(event.body.output, outputSeverity, source);
}
Promise.all(outpuPromises).then(() => outpuPromises = []);
await Promise.all(outpuPromises);
outpuPromises = [];
}));
this.rawListeners.push(this.raw.onDidBreakpoint(event => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册