mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-05 17:23:51 -05:00
Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)
* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 * fix pipelines * fix strict-null-checks * add missing files
This commit is contained in:
@@ -30,8 +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 { 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';
|
||||
@@ -65,7 +63,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
constructor(
|
||||
private _configuration: { resolved: IConfig, unresolved: IConfig | undefined },
|
||||
public root: IWorkspaceFolder,
|
||||
public root: IWorkspaceFolder | undefined,
|
||||
private model: DebugModel,
|
||||
options: IDebugSessionOptions | undefined,
|
||||
@IDebugService private readonly debugService: IDebugService,
|
||||
@@ -74,7 +72,6 @@ export class DebugSession implements IDebugSession {
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IExtensionHostDebugService private readonly extensionHostDebugService: IExtensionHostDebugService,
|
||||
@IOpenerService private readonly openerService: IOpenerService
|
||||
@@ -183,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 => {
|
||||
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);
|
||||
|
||||
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 || []);
|
||||
});
|
||||
});
|
||||
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) {
|
||||
|
||||
// __sessionID only used for EH debugging (but we add it always for now...)
|
||||
config.__sessionId = this.getId();
|
||||
|
||||
return this.raw.launchOrAttach(config).then(result => {
|
||||
return undefined;
|
||||
});
|
||||
async launchOrAttach(config: IConfig): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
}
|
||||
return Promise.reject(new Error('no debug adapter'));
|
||||
|
||||
// __sessionID only used for EH debugging (but we add it always for now...)
|
||||
config.__sessionId = this.getId();
|
||||
await this.raw.launchOrAttach(config);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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'));
|
||||
|
||||
this.cancelAllRequests();
|
||||
await this.raw.restart();
|
||||
}
|
||||
|
||||
sendBreakpoints(modelUri: URI, breakpointsToSend: IBreakpoint[], sourceModified: boolean): Promise<void> {
|
||||
|
||||
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) {
|
||||
@@ -302,233 +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 });
|
||||
const positions = response.body.breakpoints.map(bp => ({ lineNumber: bp.line, column: bp.column || 1 }));
|
||||
|
||||
return distinct(positions, p => `${p.lineNumber}:${p.column}`);
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
}
|
||||
return Promise.reject(new Error('no debug adapter'));
|
||||
|
||||
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 }));
|
||||
|
||||
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');
|
||||
}
|
||||
return Promise.reject(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 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'));
|
||||
}
|
||||
@@ -546,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 => {
|
||||
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 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
|
||||
});
|
||||
}
|
||||
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
|
||||
@@ -674,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(),
|
||||
@@ -683,7 +688,7 @@ export class DebugSession implements IDebugSession {
|
||||
stoppedDetails
|
||||
});
|
||||
}
|
||||
}) : Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
//---- private
|
||||
@@ -693,60 +698,63 @@ 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, e => {
|
||||
try {
|
||||
await this.raw.configurationDone();
|
||||
} catch (e) {
|
||||
// Disconnect the debug session on configuration done error #10596
|
||||
if (this.raw) {
|
||||
this.raw.disconnect();
|
||||
}
|
||||
if (e.command !== 'canceled' && e.message !== 'canceled') {
|
||||
this.notificationService.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
// Send all breakpoints
|
||||
this.debugService.sendAllBreakpoints(this).then(sendConfigurationDone, sendConfigurationDone)
|
||||
.then(() => this.fetchThreads());
|
||||
try {
|
||||
await this.debugService.sendAllBreakpoints(this);
|
||||
} finally {
|
||||
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 = () => {
|
||||
if (!event.body.preserveFocusHint && thread.getCallStack().length) {
|
||||
this.debugService.focusStackFrame(undefined, thread);
|
||||
if (thread.stoppedDetails) {
|
||||
if (this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak') {
|
||||
this.viewletService.openViewlet(VIEWLET_ID);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
if (this.configurationService.getValue<IDebugConfiguration>('debug').focusWindowOnBreak) {
|
||||
this.hostService.focus();
|
||||
}
|
||||
if (this.configurationService.getValue<IDebugConfiguration>('debug').focusWindowOnBreak) {
|
||||
this.hostService.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
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 => {
|
||||
@@ -763,15 +771,21 @@ export class DebugSession implements IDebugSession {
|
||||
}
|
||||
} else if (event.body.reason === 'exited') {
|
||||
this.model.clearThreads(this.getId(), true, event.body.threadId);
|
||||
const viewModel = this.debugService.getViewModel();
|
||||
const focusedThread = viewModel.focusedThread;
|
||||
if (focusedThread && event.body.threadId === focusedThread.threadId) {
|
||||
// De-focus the thread in case it was focused
|
||||
this.debugService.focusStackFrame(undefined, undefined, viewModel.focusedSession, false);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
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();
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -792,7 +806,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;
|
||||
}
|
||||
@@ -818,17 +832,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 => {
|
||||
|
||||
Reference in New Issue
Block a user