First Compile

This commit is contained in:
Felix Huang
2021-07-07 12:37:24 -07:00
committed by Yue (Felix) Huang
parent aada2f44f8
commit a83ef3a31c
7 changed files with 188 additions and 19 deletions
@@ -5,7 +5,7 @@
import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI as uri, UriComponents } from 'vs/base/common/uri';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDataBreakpoint, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDataBreakpoint, IDebugSessionOptions, IInstructionBreakpoint } from 'vs/workbench/contrib/debug/common/debug';
import {
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto, IDataBreakpointDto, IStartDebuggingOptions, IDebugConfiguration
@@ -337,7 +337,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return undefined;
}
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>)): Array<ISourceBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto> {
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint | IInstructionBreakpoint>)): Array<ISourceBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto> {
return bps.map(bp => {
if ('name' in bp) {
const fbp = <IFunctionBreakpoint>bp;
@@ -959,6 +959,19 @@ export class DebugService implements IDebugService {
await this.sendDataBreakpoints();
}
async addInstructionBreakpoint(address: string, offset: number, condition?: string, hitCondition?: string): Promise<void> {
this.model.addInstructionBreakpoint(address, offset, condition, hitCondition);
this.debugStorage.storeBreakpoints(this.model);
await this.sendInstructionBreakpoints();
this.debugStorage.storeBreakpoints(this.model);
}
async removeInstructionBreakpoints(id?: string): Promise<void> {
this.model.removeInstructionBreakpoints(id);
this.debugStorage.storeBreakpoints(this.model);
await this.sendInstructionBreakpoints();
}
setExceptionBreakpoints(data: DebugProtocol.ExceptionBreakpointsFilter[]): void {
this.model.setExceptionBreakpoints(data);
this.debugStorage.storeBreakpoints(this.model);
@@ -1003,6 +1016,16 @@ export class DebugService implements IDebugService {
});
}
private async sendInstructionBreakpoints(session?: IDebugSession): Promise<void> {
const breakpointsToSend = this.model.getInstructionBreakpoints().filter(fbp => fbp.enabled && this.model.areBreakpointsActivated());
await sendToOneOrAllSessions(this.model, session, async s => {
if (s.capabilities.supportsDataBreakpoints) {
await s.sendInstructionBreakpoints(breakpointsToSend);
}
});
}
private sendExceptionBreakpoints(session?: IDebugSession): Promise<void> {
const enabledExceptionBps = this.model.getExceptionBreakpoints().filter(exb => exb.enabled);
@@ -10,7 +10,7 @@ import severity from 'vs/base/common/severity';
import { Event, Emitter } from 'vs/base/common/event';
import { Position, IPosition } from 'vs/editor/common/core/position';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource, IDataBreakpoint, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource, IDataBreakpoint, IDebugSessionOptions, IInstructionBreakpoint } from 'vs/workbench/contrib/debug/common/debug';
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
import { mixin } from 'vs/base/common/objects';
import { Thread, ExpressionContainer, DebugModel } from 'vs/workbench/contrib/debug/common/debugModel';
@@ -447,6 +447,23 @@ export class DebugSession implements IDebugSession {
}
}
async sendInstructionBreakpoints(instructionBreakpoints: IInstructionBreakpoint[]): Promise<void> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'instruction breakpoints'));
}
if (this.raw.readyForBreakpoints) {
const response = await this.raw.setInstructionBreakpoints({ breakpoints: instructionBreakpoints });
if (response && response.body) {
const data = new Map<string, DebugProtocol.Breakpoint>();
for (let i = 0; i < instructionBreakpoints.length; i++) {
data.set(instructionBreakpoints[i].getId(), response.body.breakpoints[i]);
}
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
}
}
}
async breakpointsLocations(uri: URI, lineNumber: number): Promise<IPosition[]> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'breakpoints locations'));
@@ -536,36 +553,36 @@ export class DebugSession implements IDebugSession {
await this.raw.restartFrame({ frameId }, threadId);
}
async next(threadId: number): Promise<void> {
async next(threadId: number, granularity?: DebugProtocol.SteppingGranularity): Promise<void> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'next'));
}
await this.raw.next({ threadId });
await this.raw.next({ threadId, granularity });
}
async stepIn(threadId: number, targetId?: number): Promise<void> {
async stepIn(threadId: number, targetId?: number, granularity?: DebugProtocol.SteppingGranularity): Promise<void> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'stepIn'));
}
await this.raw.stepIn({ threadId, targetId });
await this.raw.stepIn({ threadId, targetId, granularity });
}
async stepOut(threadId: number): Promise<void> {
async stepOut(threadId: number, granularity?: DebugProtocol.SteppingGranularity): Promise<void> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'stepOut'));
}
await this.raw.stepOut({ threadId });
await this.raw.stepOut({ threadId, granularity });
}
async stepBack(threadId: number): Promise<void> {
async stepBack(threadId: number, granularity?: DebugProtocol.SteppingGranularity): Promise<void> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'stepBack'));
}
await this.raw.stepBack({ threadId });
await this.raw.stepBack({ threadId, granularity });
}
async continue(threadId: number): Promise<void> {
@@ -686,6 +703,14 @@ export class DebugSession implements IDebugSession {
return this.raw.cancel({ progressId });
}
async disassemble(memoryReference: string, offset: number, instructionOffset: number, instructionCount: number): Promise<DebugProtocol.DisassembleResponse | undefined> {
if (!this.raw) {
return Promise.reject(new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'disassemble')));
}
return this.raw.disassemble({ memoryReference, offset, instructionOffset, instructionCount, resolveSymbols: true });
}
//---- threads
getThread(threadId: number): Thread | undefined {
@@ -497,6 +497,22 @@ export class RawDebugSession implements IDisposable {
return Promise.reject(new Error('goto is not supported'));
}
async setInstructionBreakpoints(args: DebugProtocol.SetInstructionBreakpointsArguments): Promise<DebugProtocol.SetInstructionBreakpointsResponse | undefined> {
if (this.capabilities.supportsDisassembleRequest) {
return await this.send('setInstructionBreakpoints', args);
}
return Promise.reject(new Error('setInstructionBreakpoints is not supported'));
}
async disassemble(args: DebugProtocol.DisassembleArguments): Promise<DebugProtocol.DisassembleResponse | undefined> {
if (this.capabilities.supportsDisassembleRequest) {
return await this.send('disassemble', args);
}
return Promise.reject(new Error('disassemble is not supported'));
}
cancel(args: DebugProtocol.CancelArguments): Promise<DebugProtocol.CancelResponse | undefined> {
return this.send('cancel', args);
}
+20 -3
View File
@@ -255,6 +255,7 @@ export interface IDebugSession extends ITreeElement {
sendFunctionBreakpoints(fbps: IFunctionBreakpoint[]): Promise<void>;
dataBreakpointInfo(name: string, variablesReference?: number): Promise<IDataBreakpointInfoResponse | undefined>;
sendDataBreakpoints(dbps: IDataBreakpoint[]): Promise<void>;
sendInstructionBreakpoints(dbps: IInstructionBreakpoint[]): Promise<void>;
sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void>;
breakpointsLocations(uri: uri, lineNumber: number): Promise<IPosition[]>;
getDebugProtocolBreakpoint(breakpointId: string): DebugProtocol.Breakpoint | undefined;
@@ -433,6 +434,11 @@ export interface IDataBreakpoint extends IBaseBreakpoint {
readonly accessType: DebugProtocol.DataBreakpointAccessType;
}
export interface IInstructionBreakpoint extends IBaseBreakpoint {
readonly instructionReference: string;
readonly offset?: number;
}
export interface IExceptionInfo {
readonly id?: string;
readonly description?: string;
@@ -493,9 +499,9 @@ export interface IDebugModel extends ITreeElement {
* An event describing a change to the set of [breakpoints](#debug.Breakpoint).
*/
export interface IBreakpointsChangeEvent {
added?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>;
removed?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>;
changed?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>;
added?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint | IInstructionBreakpoint>;
removed?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint | IInstructionBreakpoint>;
changed?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint | IInstructionBreakpoint>;
sessionOnly: boolean;
}
@@ -887,6 +893,17 @@ export interface IDebugService {
*/
removeDataBreakpoints(id?: string): Promise<void>;
/**
* Adds a new instruction breakpoint.
*/
addInstructionBreakpoint(address: string, offset: number, condition?: string, hitCondition?: string): Promise<void>;
/**
* Removes all instruction breakpoints. If id is passed only removes the instruction breakpoint with the passed id.
* Notifies debug adapter of breakpoint changes.
*/
removeInstructionBreakpoints(id?: string): Promise<void>;
setExceptionBreakpointCondition(breakpoint: IExceptionBreakpoint, condition: string | undefined): Promise<void>;
setExceptionBreakpoints(data: DebugProtocol.ExceptionBreakpointsFilter[]): void;
@@ -14,7 +14,7 @@ import { distinct, lastIndex } from 'vs/base/common/arrays';
import { Range, IRange } from 'vs/editor/common/core/range';
import {
ITreeElement, IExpression, IExpressionContainer, IDebugSession, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IDebugModel,
IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint, State, IDataBreakpoint
IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint, State, IDataBreakpoint, IInstructionBreakpoint
} from 'vs/workbench/contrib/debug/common/debug';
import { Source, UNKNOWN_SOURCE_LABEL, getUriFromSource } from 'vs/workbench/contrib/debug/common/debugSource';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -568,6 +568,7 @@ interface IBreakpointSessionData extends DebugProtocol.Breakpoint {
supportsLogPoints: boolean;
supportsFunctionBreakpoints: boolean;
supportsDataBreakpoints: boolean;
supportsInstructionBreakpoints: boolean
sessionId: string;
}
@@ -577,7 +578,8 @@ function toBreakpointSessionData(data: DebugProtocol.Breakpoint, capabilities: D
supportsHitConditionalBreakpoints: !!capabilities.supportsHitConditionalBreakpoints,
supportsLogPoints: !!capabilities.supportsLogPoints,
supportsFunctionBreakpoints: !!capabilities.supportsFunctionBreakpoints,
supportsDataBreakpoints: !!capabilities.supportsDataBreakpoints
supportsDataBreakpoints: !!capabilities.supportsDataBreakpoints,
supportsInstructionBreakpoints: !!capabilities.supportsInstructionBreakpoints
}, data);
}
@@ -761,7 +763,6 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint {
return true;
}
override setSessionData(sessionId: string, data: IBreakpointSessionData | undefined): void {
super.setSessionData(sessionId, data);
if (!this._adapterData) {
@@ -908,6 +909,41 @@ export class ExceptionBreakpoint extends BaseBreakpoint implements IExceptionBre
}
}
export class InstructionBreakpoint extends BaseBreakpoint implements IInstructionBreakpoint {
constructor(
public instructionReference: string,
public offset: number,
public canPersist: boolean,
enabled: boolean,
hitCondition: string | undefined,
condition: string | undefined,
logMessage: string | undefined,
id = generateUuid()
) {
super(enabled, hitCondition, condition, logMessage, id);
}
override toJSON(): any {
const result = super.toJSON();
result.instructionReference = this.instructionReference;
result.offset = this.offset;
return result;
}
get supported(): boolean {
if (!this.data) {
return true;
}
return this.data.supportsInstructionBreakpoints;
}
override toString(): string {
return this.instructionReference;
}
}
export class ThreadAndSessionIds implements ITreeElement {
constructor(public sessionId: string, public threadId: number) { }
@@ -929,6 +965,7 @@ export class DebugModel implements IDebugModel {
private exceptionBreakpoints: ExceptionBreakpoint[];
private dataBreakopints: DataBreakpoint[];
private watchExpressions: Expression[];
private instructionBreakpoints: InstructionBreakpoint[];
constructor(
debugStorage: DebugStorage,
@@ -940,6 +977,7 @@ export class DebugModel implements IDebugModel {
this.exceptionBreakpoints = debugStorage.loadExceptionBreakpoints();
this.dataBreakopints = debugStorage.loadDataBreakpoints();
this.watchExpressions = debugStorage.loadWatchExpressions();
this.instructionBreakpoints = [];
this.sessions = [];
}
@@ -1095,6 +1133,10 @@ export class DebugModel implements IDebugModel {
return this.exceptionBreakpoints;
}
getInstructionBreakpoints(): IInstructionBreakpoint[] {
return this.instructionBreakpoints;
}
setExceptionBreakpoints(data: DebugProtocol.ExceptionBreakpointsFilter[]): void {
if (data) {
if (this.exceptionBreakpoints.length === data.length && this.exceptionBreakpoints.every((exbp, i) =>
@@ -1197,6 +1239,16 @@ export class DebugModel implements IDebugModel {
}
}
});
this.instructionBreakpoints.forEach(ibp => {
if (!data) {
ibp.setSessionData(sessionId, undefined);
} else {
const dbpData = data.get(ibp.getId());
if (dbpData) {
ibp.setSessionData(sessionId, toBreakpointSessionData(dbpData, capabilites));
}
}
});
this._onDidChangeBreakpoints.fire({
sessionOnly: true
@@ -1245,7 +1297,7 @@ export class DebugModel implements IDebugModel {
}
enableOrDisableAllBreakpoints(enable: boolean): void {
const changed: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint> = [];
const changed: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint | InstructionBreakpoint> = [];
this.breakpoints.forEach(bp => {
if (bp.enabled !== enable) {
@@ -1265,6 +1317,13 @@ export class DebugModel implements IDebugModel {
}
dbp.enabled = enable;
});
this.instructionBreakpoints.forEach(ibp => {
if (ibp.enabled !== enable) {
changed.push(ibp);
}
ibp.enabled = enable;
});
if (enable) {
this.breakpointsActivated = true;
}
@@ -1326,6 +1385,24 @@ export class DebugModel implements IDebugModel {
this._onDidChangeBreakpoints.fire({ removed, sessionOnly: false });
}
addInstructionBreakpoint(instructionReference: string, offset: number, condition?: string, hitCondition?: string): void {
const newInstructionBreakpoint = new InstructionBreakpoint(instructionReference, offset, false, true, hitCondition, condition, undefined);
this.instructionBreakpoints.push(newInstructionBreakpoint);
this._onDidChangeBreakpoints.fire({ added: [newInstructionBreakpoint], sessionOnly: true });
}
removeInstructionBreakpoints(id?: string): void {
let removed: InstructionBreakpoint[];
if (id) {
removed = this.instructionBreakpoints.filter(fbp => fbp.getId() === id);
this.instructionBreakpoints = this.instructionBreakpoints.filter(fbp => fbp.getId() !== id);
} else {
removed = this.instructionBreakpoints;
this.instructionBreakpoints = [];
}
this._onDidChangeBreakpoints.fire({ removed, sessionOnly: false });
}
getWatchExpressions(): Expression[] {
return this.watchExpressions;
}
@@ -7,7 +7,7 @@ import { URI as uri } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { Position, IPosition } from 'vs/editor/common/core/position';
import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IDebugModel, IViewModel, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate, IFunctionBreakpoint, IExceptionBreakpoint, IDebugger, IExceptionInfo, AdapterEndEvent, IReplElement, IExpression, IReplElementSource, IDataBreakpoint, IDebugSessionOptions, IEvaluate, IAdapterManager, IRawStoppedDetails } from 'vs/workbench/contrib/debug/common/debug';
import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IDebugModel, IViewModel, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate, IFunctionBreakpoint, IExceptionBreakpoint, IDebugger, IExceptionInfo, AdapterEndEvent, IReplElement, IExpression, IReplElementSource, IDataBreakpoint, IDebugSessionOptions, IEvaluate, IAdapterManager, IRawStoppedDetails, IInstructionBreakpoint } from 'vs/workbench/contrib/debug/common/debug';
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
import Severity from 'vs/base/common/severity';
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
@@ -86,6 +86,14 @@ export class MockDebugService implements IDebugService {
throw new Error('not implemented');
}
addInstructionBreakpoint(address: string, offset: number, condition?: string, hitCondition?: string): Promise<void> {
throw new Error('Method not implemented.');
}
removeInstructionBreakpoints(address?: string): Promise<void> {
throw new Error('Method not implemented.');
}
setExceptionBreakpointCondition(breakpoint: IExceptionBreakpoint, condition: string): Promise<void> {
throw new Error('Method not implemented.');
}
@@ -323,6 +331,9 @@ export class MockSession implements IDebugSession {
sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void> {
throw new Error('Method not implemented.');
}
sendInstructionBreakpoints(dbps: IInstructionBreakpoint[]): Promise<void> {
throw new Error('Method not implemented.');
}
getDebugProtocolBreakpoint(breakpointId: string): DebugProtocol.Breakpoint | undefined {
throw new Error('Method not implemented.');
}