mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 04:49:35 +00:00
debug: support data breakpoints by address (#206855)
This creates a new "Add Data Breakpoint at Address" action in the breakpoints view when a debugger that supports the capability is available. It prompts the user to enter their address in a quickpick, and then allows them to choose appropriate data access settings. The editor side of https://github.com/microsoft/debug-adapter-protocol/issues/455
This commit is contained in:
parent
191be39e5a
commit
d73fa8b14a
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { DisposableMap, DisposableStore, IDisposable, toDisposable } 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, IInstructionBreakpoint, DebugConfigurationProviderTriggerKind, IDebugVisualization } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDataBreakpoint, IDebugSessionOptions, IInstructionBreakpoint, DebugConfigurationProviderTriggerKind, IDebugVisualization, DataBreakpointSetType } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import {
|
||||
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
|
||||
IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto, IDataBreakpointDto, IStartDebuggingOptions, IDebugConfiguration, IThreadFocusDto, IStackFrameFocusDto
|
||||
|
@ -225,7 +225,14 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
|||
} else if (dto.type === 'function') {
|
||||
this.debugService.addFunctionBreakpoint(dto.functionName, dto.id, dto.mode);
|
||||
} else if (dto.type === 'data') {
|
||||
this.debugService.addDataBreakpoint(dto.label, dto.dataId, dto.canPersist, dto.accessTypes, dto.accessType, dto.mode);
|
||||
this.debugService.addDataBreakpoint({
|
||||
description: dto.label,
|
||||
src: { type: DataBreakpointSetType.Variable, dataId: dto.dataId },
|
||||
canPersist: dto.canPersist,
|
||||
accessTypes: dto.accessTypes,
|
||||
accessType: dto.accessType,
|
||||
mode: dto.mode
|
||||
});
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
|
@ -436,19 +443,20 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
|||
logMessage: fbp.logMessage,
|
||||
functionName: fbp.name
|
||||
};
|
||||
} else if ('dataId' in bp) {
|
||||
} else if ('src' in bp) {
|
||||
const dbp = <IDataBreakpoint>bp;
|
||||
return <IDataBreakpointDto>{
|
||||
return {
|
||||
type: 'data',
|
||||
id: dbp.getId(),
|
||||
dataId: dbp.dataId,
|
||||
dataId: dbp.src.type === DataBreakpointSetType.Variable ? dbp.src.dataId : dbp.src.address,
|
||||
enabled: dbp.enabled,
|
||||
condition: dbp.condition,
|
||||
hitCondition: dbp.hitCondition,
|
||||
logMessage: dbp.logMessage,
|
||||
accessType: dbp.accessType,
|
||||
label: dbp.description,
|
||||
canPersist: dbp.canPersist
|
||||
};
|
||||
} satisfies IDataBreakpointDto;
|
||||
} else {
|
||||
const sbp = <IBreakpoint>bp;
|
||||
return <ISourceBreakpointDto>{
|
||||
|
|
|
@ -51,10 +51,11 @@ import { IEditorPane } from 'vs/workbench/common/editor';
|
|||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons';
|
||||
import { DisassemblyView } from 'vs/workbench/contrib/debug/browser/disassemblyView';
|
||||
import { BREAKPOINTS_VIEW_ID, BREAKPOINT_EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINTS_EXIST, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_BREAKPOINT_HAS_MODES, CONTEXT_BREAKPOINT_INPUT_FOCUSED, CONTEXT_BREAKPOINT_ITEM_TYPE, CONTEXT_BREAKPOINT_SUPPORTS_CONDITION, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_IN_DEBUG_MODE, DEBUG_SCHEME, DebuggerString, IBaseBreakpoint, IBreakpoint, IBreakpointEditorContribution, IBreakpointUpdateData, IDataBreakpoint, IDebugModel, IDebugService, IEnablement, IExceptionBreakpoint, IFunctionBreakpoint, IInstructionBreakpoint, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { BREAKPOINTS_VIEW_ID, BREAKPOINT_EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINTS_EXIST, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_BREAKPOINT_HAS_MODES, CONTEXT_BREAKPOINT_INPUT_FOCUSED, CONTEXT_BREAKPOINT_ITEM_IS_DATA_BYTES, CONTEXT_BREAKPOINT_ITEM_TYPE, CONTEXT_BREAKPOINT_SUPPORTS_CONDITION, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_IN_DEBUG_MODE, CONTEXT_SET_DATA_BREAKPOINT_BYTES_SUPPORTED, DEBUG_SCHEME, DataBreakpointSetType, DataBreakpointSource, DebuggerString, IBaseBreakpoint, IBreakpoint, IBreakpointEditorContribution, IBreakpointUpdateData, IDataBreakpoint, IDataBreakpointInfoResponse, IDebugModel, IDebugService, IEnablement, IExceptionBreakpoint, IFunctionBreakpoint, IInstructionBreakpoint, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Breakpoint, DataBreakpoint, ExceptionBreakpoint, FunctionBreakpoint, InstructionBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { DisassemblyViewInput } from 'vs/workbench/contrib/debug/common/disassemblyViewInput';
|
||||
import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
|
@ -87,6 +88,7 @@ export class BreakpointsView extends ViewPane {
|
|||
private ignoreLayout = false;
|
||||
private menu: IMenu;
|
||||
private breakpointItemType: IContextKey<string | undefined>;
|
||||
private breakpointIsDataBytes: IContextKey<boolean | undefined>;
|
||||
private breakpointHasMultipleModes: IContextKey<boolean>;
|
||||
private breakpointSupportsCondition: IContextKey<boolean>;
|
||||
private _inputBoxData: InputBoxData | undefined;
|
||||
|
@ -120,6 +122,7 @@ export class BreakpointsView extends ViewPane {
|
|||
this.menu = menuService.createMenu(MenuId.DebugBreakpointsContext, contextKeyService);
|
||||
this._register(this.menu);
|
||||
this.breakpointItemType = CONTEXT_BREAKPOINT_ITEM_TYPE.bindTo(contextKeyService);
|
||||
this.breakpointIsDataBytes = CONTEXT_BREAKPOINT_ITEM_IS_DATA_BYTES.bindTo(contextKeyService);
|
||||
this.breakpointHasMultipleModes = CONTEXT_BREAKPOINT_HAS_MODES.bindTo(contextKeyService);
|
||||
this.breakpointSupportsCondition = CONTEXT_BREAKPOINT_SUPPORTS_CONDITION.bindTo(contextKeyService);
|
||||
this.breakpointInputFocused = CONTEXT_BREAKPOINT_INPUT_FOCUSED.bindTo(contextKeyService);
|
||||
|
@ -142,7 +145,7 @@ export class BreakpointsView extends ViewPane {
|
|||
new ExceptionBreakpointInputRenderer(this, this.debugService, this.contextViewService),
|
||||
this.instantiationService.createInstance(FunctionBreakpointsRenderer, this.menu, this.breakpointSupportsCondition, this.breakpointItemType),
|
||||
new FunctionBreakpointInputRenderer(this, this.debugService, this.contextViewService, this.labelService),
|
||||
this.instantiationService.createInstance(DataBreakpointsRenderer, this.menu, this.breakpointHasMultipleModes, this.breakpointSupportsCondition, this.breakpointItemType),
|
||||
this.instantiationService.createInstance(DataBreakpointsRenderer, this.menu, this.breakpointHasMultipleModes, this.breakpointSupportsCondition, this.breakpointItemType, this.breakpointIsDataBytes),
|
||||
new DataBreakpointInputRenderer(this, this.debugService, this.contextViewService, this.labelService),
|
||||
this.instantiationService.createInstance(InstructionBreakpointsRenderer),
|
||||
], {
|
||||
|
@ -266,6 +269,7 @@ export class BreakpointsView extends ViewPane {
|
|||
const session = this.debugService.getViewModel().focusedSession;
|
||||
const conditionSupported = element instanceof ExceptionBreakpoint ? element.supportsCondition : (!session || !!session.capabilities.supportsConditionalBreakpoints);
|
||||
this.breakpointSupportsCondition.set(conditionSupported);
|
||||
this.breakpointIsDataBytes.set(element instanceof DataBreakpoint && element.src.type === DataBreakpointSetType.Address);
|
||||
|
||||
const secondary: IAction[] = [];
|
||||
createAndFillInContextMenuActions(this.menu, { arg: e.element, shouldForwardArgs: false }, { primary: [], secondary }, 'inline');
|
||||
|
@ -740,6 +744,7 @@ class DataBreakpointsRenderer implements IListRenderer<DataBreakpoint, IDataBrea
|
|||
private breakpointHasMultipleModes: IContextKey<boolean>,
|
||||
private breakpointSupportsCondition: IContextKey<boolean>,
|
||||
private breakpointItemType: IContextKey<string | undefined>,
|
||||
private breakpointIsDataBytes: IContextKey<boolean | undefined>,
|
||||
@IDebugService private readonly debugService: IDebugService,
|
||||
@ILabelService private readonly labelService: ILabelService
|
||||
) {
|
||||
|
@ -816,10 +821,12 @@ class DataBreakpointsRenderer implements IListRenderer<DataBreakpoint, IDataBrea
|
|||
this.breakpointSupportsCondition.set(!session || !!session.capabilities.supportsConditionalBreakpoints);
|
||||
this.breakpointHasMultipleModes.set(this.debugService.getModel().getBreakpointModes('data').length > 1);
|
||||
this.breakpointItemType.set('dataBreakpoint');
|
||||
this.breakpointIsDataBytes.set(dataBreakpoint.src.type === DataBreakpointSetType.Address);
|
||||
createAndFillInActionBarActions(this.menu, { arg: dataBreakpoint, shouldForwardArgs: true }, { primary, secondary: [] }, 'inline');
|
||||
data.actionBar.clear();
|
||||
data.actionBar.push(primary, { icon: true, label: false });
|
||||
breakpointIdToActionBarDomeNode.set(dataBreakpoint.getId(), data.actionBar.domNode);
|
||||
this.breakpointIsDataBytes.reset();
|
||||
}
|
||||
|
||||
disposeTemplate(templateData: IBaseBreakpointWithIconTemplateData): void {
|
||||
|
@ -1421,6 +1428,166 @@ registerAction2(class extends Action2 {
|
|||
}
|
||||
});
|
||||
|
||||
abstract class MemoryBreakpointAction extends Action2 {
|
||||
async run(accessor: ServicesAccessor, existingBreakpoint?: IDataBreakpoint): Promise<void> {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
const session = debugService.getViewModel().focusedSession;
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
let defaultValue = undefined;
|
||||
if (existingBreakpoint && existingBreakpoint.src.type === DataBreakpointSetType.Address) {
|
||||
defaultValue = `${existingBreakpoint.src.address} + ${existingBreakpoint.src.bytes}`;
|
||||
}
|
||||
|
||||
const quickInput = accessor.get(IQuickInputService);
|
||||
const notifications = accessor.get(INotificationService);
|
||||
const range = await this.getRange(quickInput, defaultValue);
|
||||
if (!range) {
|
||||
return;
|
||||
}
|
||||
|
||||
let info: IDataBreakpointInfoResponse | undefined;
|
||||
try {
|
||||
info = await session.dataBytesBreakpointInfo(range.address, range.bytes);
|
||||
} catch (e) {
|
||||
notifications.error(localize('dataBreakpointError', "Failed to set data breakpoint at {0}: {1}", range.address, e.message));
|
||||
}
|
||||
|
||||
if (!info?.dataId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let accessType: DebugProtocol.DataBreakpointAccessType = 'write';
|
||||
if (info.accessTypes && info.accessTypes?.length > 1) {
|
||||
const accessTypes = info.accessTypes.map(type => ({ label: type }));
|
||||
const selectedAccessType = await quickInput.pick(accessTypes, { placeHolder: localize('dataBreakpointAccessType', "Select the access type to monitor") });
|
||||
if (!selectedAccessType) {
|
||||
return;
|
||||
}
|
||||
|
||||
accessType = selectedAccessType.label;
|
||||
}
|
||||
|
||||
const src: DataBreakpointSource = { type: DataBreakpointSetType.Address, ...range };
|
||||
if (existingBreakpoint) {
|
||||
await debugService.removeDataBreakpoints(existingBreakpoint.getId());
|
||||
}
|
||||
|
||||
await debugService.addDataBreakpoint({
|
||||
description: info.description,
|
||||
src,
|
||||
canPersist: true,
|
||||
accessTypes: info.accessTypes,
|
||||
accessType: accessType,
|
||||
initialSessionData: { session, dataId: info.dataId }
|
||||
});
|
||||
}
|
||||
|
||||
private getRange(quickInput: IQuickInputService, defaultValue?: string) {
|
||||
return new Promise<{ address: string; bytes: number } | undefined>(resolve => {
|
||||
const input = quickInput.createInputBox();
|
||||
input.prompt = localize('dataBreakpointMemoryRangePrompt', "Enter a memory range in which to break");
|
||||
input.placeholder = localize('dataBreakpointMemoryRangePlaceholder', 'Absolute range (0x1234 - 0x1300) or range of bytes after an address (0x1234 + 0xff)');
|
||||
if (defaultValue) {
|
||||
input.value = defaultValue;
|
||||
input.valueSelection = [0, defaultValue.length];
|
||||
}
|
||||
input.onDidChangeValue(e => {
|
||||
const err = this.parseAddress(e, false);
|
||||
input.validationMessage = err?.error;
|
||||
});
|
||||
input.onDidAccept(() => {
|
||||
const r = this.parseAddress(input.value, true);
|
||||
if ('error' in r) {
|
||||
input.validationMessage = r.error;
|
||||
} else {
|
||||
resolve(r);
|
||||
}
|
||||
input.dispose();
|
||||
});
|
||||
input.onDidHide(() => {
|
||||
resolve(undefined);
|
||||
input.dispose();
|
||||
});
|
||||
input.ignoreFocusOut = true;
|
||||
input.show();
|
||||
});
|
||||
}
|
||||
|
||||
private parseAddress(range: string, isFinal: false): { error: string } | undefined;
|
||||
private parseAddress(range: string, isFinal: true): { error: string } | { address: string; bytes: number };
|
||||
private parseAddress(range: string, isFinal: boolean): { error: string } | { address: string; bytes: number } | undefined {
|
||||
const parts = /^(\S+)\s*(?:([+-])\s*(\S+))?/.exec(range);
|
||||
if (!parts) {
|
||||
return { error: localize('dataBreakpointAddrFormat', 'Address should be a range of numbers the form "[Start] - [End]" or "[Start] + [Bytes]"') };
|
||||
}
|
||||
|
||||
const isNum = (e: string) => isFinal ? /^0x[0-9a-f]*|[0-9]*$/i.test(e) : /^0x[0-9a-f]+|[0-9]+$/i.test(e);
|
||||
const [, startStr, sign = '+', endStr = '1'] = parts;
|
||||
|
||||
for (const n of [startStr, endStr]) {
|
||||
if (!isNum(n)) {
|
||||
return { error: localize('dataBreakpointAddrStartEnd', 'Number must be a decimal integer or hex value starting with \"0x\", got {0}', n) };
|
||||
}
|
||||
}
|
||||
|
||||
if (!isFinal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const start = BigInt(startStr);
|
||||
const end = BigInt(endStr);
|
||||
const address = `0x${start.toString(16)}`;
|
||||
if (sign === '-') {
|
||||
return { address, bytes: Number(start - end) };
|
||||
}
|
||||
|
||||
return { address, bytes: Number(end) };
|
||||
}
|
||||
}
|
||||
|
||||
registerAction2(class extends MemoryBreakpointAction {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.debug.viewlet.action.addDataBreakpointOnAddress',
|
||||
title: {
|
||||
...localize2('addDataBreakpointOnAddress', "Add Data Breakpoint at Address"),
|
||||
mnemonicTitle: localize({ key: 'miDataBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Data Breakpoint..."),
|
||||
},
|
||||
f1: true,
|
||||
icon: icons.watchExpressionsAddDataBreakpoint,
|
||||
menu: [{
|
||||
id: MenuId.ViewTitle,
|
||||
group: 'navigation',
|
||||
order: 11,
|
||||
when: ContextKeyExpr.and(CONTEXT_SET_DATA_BREAKPOINT_BYTES_SUPPORTED, ContextKeyExpr.equals('view', BREAKPOINTS_VIEW_ID))
|
||||
}, {
|
||||
id: MenuId.MenubarNewBreakpointMenu,
|
||||
group: '1_breakpoints',
|
||||
order: 4,
|
||||
when: CONTEXT_SET_DATA_BREAKPOINT_BYTES_SUPPORTED
|
||||
}]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
registerAction2(class extends MemoryBreakpointAction {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.debug.viewlet.action.editDataBreakpointOnAddress',
|
||||
title: localize2('editDataBreakpointOnAddress', "Edit Address..."),
|
||||
menu: [{
|
||||
id: MenuId.DebugBreakpointsContext,
|
||||
when: ContextKeyExpr.and(CONTEXT_SET_DATA_BREAKPOINT_BYTES_SUPPORTED, CONTEXT_BREAKPOINT_ITEM_IS_DATA_BYTES),
|
||||
group: 'navigation',
|
||||
order: 15,
|
||||
}]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
|
|
|
@ -79,6 +79,7 @@ export const watchExpressionsRemoveAll = registerIcon('watch-expressions-remove-
|
|||
export const watchExpressionRemove = registerIcon('watch-expression-remove', Codicon.removeClose, localize('watchExpressionRemove', 'Icon for the Remove action in the watch view.'));
|
||||
export const watchExpressionsAdd = registerIcon('watch-expressions-add', Codicon.add, localize('watchExpressionsAdd', 'Icon for the add action in the watch view.'));
|
||||
export const watchExpressionsAddFuncBreakpoint = registerIcon('watch-expressions-add-function-breakpoint', Codicon.add, localize('watchExpressionsAddFuncBreakpoint', 'Icon for the add function breakpoint action in the watch view.'));
|
||||
export const watchExpressionsAddDataBreakpoint = registerIcon('watch-expressions-add-data-breakpoint', Codicon.variableGroup, localize('watchExpressionsAddDataBreakpoint', 'Icon for the add data breakpoint action in the breakpoints view.'));
|
||||
|
||||
export const breakpointsRemoveAll = registerIcon('breakpoints-remove-all', Codicon.closeAll, localize('breakpointsRemoveAll', 'Icon for the Remove All action in the breakpoints view.'));
|
||||
export const breakpointsActivate = registerIcon('breakpoints-activate', Codicon.activateBreakpoints, localize('breakpointsActivate', 'Icon for the activate action in the breakpoints view.'));
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { raceTimeout, RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { RunOnceScheduler, raceTimeout } from 'vs/base/common/async';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { isErrorWithActions } from 'vs/base/common/errorMessage';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
|
@ -24,7 +24,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { FileChangesEvent, FileChangeType, IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileChangeType, FileChangesEvent, IFileService } from 'vs/platform/files/common/files';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
|
@ -34,22 +34,21 @@ import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/work
|
|||
import { EditorsOrder } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
|
||||
import { AdapterManager } from 'vs/workbench/contrib/debug/browser/debugAdapterManager';
|
||||
import { DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands';
|
||||
import { ConfigurationManager } from 'vs/workbench/contrib/debug/browser/debugConfigurationManager';
|
||||
import { DebugMemoryFileSystemProvider } from 'vs/workbench/contrib/debug/browser/debugMemory';
|
||||
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
|
||||
import { DebugTaskRunner, TaskRunResult } from 'vs/workbench/contrib/debug/browser/debugTaskRunner';
|
||||
import { CALLSTACK_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, CONTEXT_HAS_DEBUGGED, CONTEXT_DEBUG_STATE, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_UX, CONTEXT_DISASSEMBLY_VIEW_FOCUS, CONTEXT_IN_DEBUG_MODE, debuggerDisabledMessage, DEBUG_MEMORY_SCHEME, getStateLabel, IAdapterManager, IBreakpoint, IBreakpointData, ICompound, IConfig, IConfigurationManager, IDebugConfiguration, IDebugModel, IDebugService, IDebugSession, IDebugSessionOptions, IEnablement, IExceptionBreakpoint, IGlobalConfig, ILaunch, IStackFrame, IThread, IViewModel, REPL_VIEW_ID, State, VIEWLET_ID, DEBUG_SCHEME, IBreakpointUpdateData } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { CALLSTACK_VIEW_ID, CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_STATE, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_UX, CONTEXT_DISASSEMBLY_VIEW_FOCUS, CONTEXT_HAS_DEBUGGED, CONTEXT_IN_DEBUG_MODE, DEBUG_MEMORY_SCHEME, DEBUG_SCHEME, IAdapterManager, IBreakpoint, IBreakpointData, IBreakpointUpdateData, ICompound, IConfig, IConfigurationManager, IDebugConfiguration, IDebugModel, IDebugService, IDebugSession, IDebugSessionOptions, IEnablement, IExceptionBreakpoint, IGlobalConfig, ILaunch, IStackFrame, IThread, IViewModel, REPL_VIEW_ID, State, VIEWLET_ID, debuggerDisabledMessage, getStateLabel } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { DebugCompoundRoot } from 'vs/workbench/contrib/debug/common/debugCompoundRoot';
|
||||
import { Debugger } from 'vs/workbench/contrib/debug/common/debugger';
|
||||
import { Breakpoint, DataBreakpoint, DebugModel, FunctionBreakpoint, IInstructionBreakpointOptions, InstructionBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { Breakpoint, DataBreakpoint, DebugModel, FunctionBreakpoint, IDataBreakpointOptions, IInstructionBreakpointOptions, InstructionBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
import { DebugStorage } from 'vs/workbench/contrib/debug/common/debugStorage';
|
||||
import { DebugTelemetry } from 'vs/workbench/contrib/debug/common/debugTelemetry';
|
||||
import { getExtensionHostDebugSession, saveAllBeforeDebugStart } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { ViewModel } from 'vs/workbench/contrib/debug/common/debugViewModel';
|
||||
import { Debugger } from 'vs/workbench/contrib/debug/common/debugger';
|
||||
import { DisassemblyViewInput } from 'vs/workbench/contrib/debug/common/disassemblyViewInput';
|
||||
import { VIEWLET_ID as EXPLORER_VIEWLET_ID } from 'vs/workbench/contrib/files/common/files';
|
||||
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
|
@ -58,6 +57,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
|
|||
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
|
||||
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
|
||||
|
||||
export class DebugService implements IDebugService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
@ -1081,8 +1081,8 @@ export class DebugService implements IDebugService {
|
|||
await this.sendFunctionBreakpoints();
|
||||
}
|
||||
|
||||
async addDataBreakpoint(description: string, dataId: string, canPersist: boolean, accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined, accessType: DebugProtocol.DataBreakpointAccessType, mode: string | undefined): Promise<void> {
|
||||
this.model.addDataBreakpoint({ description, dataId, canPersist, accessTypes, accessType, mode });
|
||||
async addDataBreakpoint(opts: IDataBreakpointOptions): Promise<void> {
|
||||
this.model.addDataBreakpoint(opts);
|
||||
this.debugStorage.storeBreakpoints(this.model);
|
||||
await this.sendDataBreakpoints();
|
||||
this.debugStorage.storeBreakpoints(this.model);
|
||||
|
|
|
@ -29,7 +29,7 @@ import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'
|
|||
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { RawDebugSession } from 'vs/workbench/contrib/debug/browser/rawDebugSession';
|
||||
import { AdapterEndEvent, IBreakpoint, IConfig, IDataBreakpoint, IDebugConfiguration, IDebugService, IDebugSession, IDebugSessionOptions, IDebugger, IExceptionBreakpoint, IExceptionInfo, IFunctionBreakpoint, IInstructionBreakpoint, IMemoryRegion, IRawModelUpdate, IRawStoppedDetails, IReplElement, IStackFrame, IThread, LoadedSourceEvent, State, VIEWLET_ID } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { AdapterEndEvent, IBreakpoint, IConfig, IDataBreakpoint, IDataBreakpointInfoResponse, IDebugConfiguration, IDebugService, IDebugSession, IDebugSessionOptions, IDebugger, IExceptionBreakpoint, IExceptionInfo, IFunctionBreakpoint, IInstructionBreakpoint, IMemoryRegion, IRawModelUpdate, IRawStoppedDetails, IReplElement, IStackFrame, IThread, LoadedSourceEvent, State, VIEWLET_ID } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { DebugCompoundRoot } from 'vs/workbench/contrib/debug/common/debugCompoundRoot';
|
||||
import { DebugModel, ExpressionContainer, MemoryRegion, Thread } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
|
@ -41,6 +41,7 @@ import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecy
|
|||
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
|
||||
import { getActiveWindow } from 'vs/base/browser/dom';
|
||||
import { mainWindow } from 'vs/base/browser/window';
|
||||
import { isDefined } from 'vs/base/common/types';
|
||||
|
||||
const TRIGGERED_BREAKPOINT_MAX_DELAY = 1500;
|
||||
|
||||
|
@ -461,7 +462,7 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
breakpoints: breakpointsToSend.map(bp => bp.toDAP()),
|
||||
sourceModified
|
||||
});
|
||||
if (response && response.body) {
|
||||
if (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]);
|
||||
|
@ -478,7 +479,7 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
|
||||
if (this.raw.readyForBreakpoints) {
|
||||
const response = await this.raw.setFunctionBreakpoints({ breakpoints: fbpts.map(bp => bp.toDAP()) });
|
||||
if (response && response.body) {
|
||||
if (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]);
|
||||
|
@ -506,7 +507,7 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
} : { filters: exbpts.map(exb => exb.filter) };
|
||||
|
||||
const response = await this.raw.setExceptionBreakpoints(args);
|
||||
if (response && response.body && response.body.breakpoints) {
|
||||
if (response?.body && response.body.breakpoints) {
|
||||
const data = new Map<string, DebugProtocol.Breakpoint>();
|
||||
for (let i = 0; i < exbpts.length; i++) {
|
||||
data.set(exbpts[i].getId(), response.body.breakpoints[i]);
|
||||
|
@ -517,7 +518,19 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
async dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null; description: string; canPersist?: boolean } | undefined> {
|
||||
dataBytesBreakpointInfo(address: string, bytes: number): Promise<IDataBreakpointInfoResponse | undefined> {
|
||||
if (this.raw?.capabilities.supportsDataBreakpointBytes === false) {
|
||||
throw new Error(localize('sessionDoesNotSupporBytesBreakpoints', "Session does not support breakpoints with bytes"));
|
||||
}
|
||||
|
||||
return this._dataBreakpointInfo({ name: address, bytes, asAddress: true });
|
||||
}
|
||||
|
||||
dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null; description: string; canPersist?: boolean } | undefined> {
|
||||
return this._dataBreakpointInfo({ name, variablesReference });
|
||||
}
|
||||
|
||||
private async _dataBreakpointInfo(args: DebugProtocol.DataBreakpointInfoArguments): Promise<{ dataId: string | null; description: string; canPersist?: boolean } | undefined> {
|
||||
if (!this.raw) {
|
||||
throw new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'data breakpoints info'));
|
||||
}
|
||||
|
@ -525,7 +538,7 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
throw new Error(localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints"));
|
||||
}
|
||||
|
||||
const response = await this.raw.dataBreakpointInfo({ name, variablesReference });
|
||||
const response = await this.raw.dataBreakpointInfo(args);
|
||||
return response?.body;
|
||||
}
|
||||
|
||||
|
@ -535,11 +548,24 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
}
|
||||
|
||||
if (this.raw.readyForBreakpoints) {
|
||||
const response = await this.raw.setDataBreakpoints({ breakpoints: dataBreakpoints.map(bp => bp.toDAP()) });
|
||||
if (response && response.body) {
|
||||
const converted = await Promise.all(dataBreakpoints.map(async bp => {
|
||||
try {
|
||||
const dap = await bp.toDAP(this);
|
||||
return { dap, bp };
|
||||
} catch (e) {
|
||||
return { bp, message: e.message };
|
||||
}
|
||||
}));
|
||||
const response = await this.raw.setDataBreakpoints({ breakpoints: converted.map(d => d.dap).filter(isDefined) });
|
||||
if (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]);
|
||||
let i = 0;
|
||||
for (const dap of converted) {
|
||||
if (!dap.dap) {
|
||||
data.set(dap.bp.getId(), dap.message);
|
||||
} else if (i < response.body.breakpoints.length) {
|
||||
data.set(dap.bp.getId(), response.body.breakpoints[i++]);
|
||||
}
|
||||
}
|
||||
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
|
||||
}
|
||||
|
@ -553,7 +579,7 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
|
||||
if (this.raw.readyForBreakpoints) {
|
||||
const response = await this.raw.setInstructionBreakpoints({ breakpoints: instructionBreakpoints.map(ib => ib.toDAP()) });
|
||||
if (response && response.body) {
|
||||
if (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]);
|
||||
|
@ -790,7 +816,7 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
}
|
||||
|
||||
const response = await this.raw.loadedSources({});
|
||||
if (response && response.body && response.body.sources) {
|
||||
if (response?.body && response.body.sources) {
|
||||
return response.body.sources.map(src => this.getSource(src));
|
||||
} else {
|
||||
return [];
|
||||
|
@ -959,7 +985,7 @@ export class DebugSession implements IDebugSession, IDisposable {
|
|||
private async fetchThreads(stoppedDetails?: IRawStoppedDetails): Promise<void> {
|
||||
if (this.raw) {
|
||||
const response = await this.raw.threads();
|
||||
if (response && response.body && response.body.threads) {
|
||||
if (response?.body && response.body.threads) {
|
||||
this.model.rawUpdate({
|
||||
sessionId: this.getId(),
|
||||
threads: response.body.threads,
|
||||
|
|
|
@ -39,7 +39,7 @@ import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewl
|
|||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { AbstractExpressionDataSource, AbstractExpressionsRenderer, IExpressionTemplateData, IInputBoxOptions, renderExpressionValue, renderVariable, renderViewTree } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
|
||||
import { CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_ACCESSED_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_READ_SUPPORTED, CONTEXT_VARIABLES_FOCUSED, DebugVisualizationType, IDataBreakpointInfoResponse, IDebugService, IExpression, IScope, IStackFrame, IViewModel, VARIABLES_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_ACCESSED_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_READ_SUPPORTED, CONTEXT_VARIABLES_FOCUSED, DataBreakpointSetType, DebugVisualizationType, IDataBreakpointInfoResponse, IDebugService, IExpression, IScope, IStackFrame, IViewModel, VARIABLES_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { getContextForVariable } from 'vs/workbench/contrib/debug/common/debugContext';
|
||||
import { ErrorScope, Expression, Scope, StackFrame, Variable, VisualizedExpression, getUriForDebugMemory } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { DebugVisualizer, IDebugVisualizerService } from 'vs/workbench/contrib/debug/common/debugVisualizers';
|
||||
|
@ -766,7 +766,7 @@ CommandsRegistry.registerCommand({
|
|||
handler: async (accessor: ServicesAccessor) => {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
if (dataBreakpointInfoResponse) {
|
||||
await debugService.addDataBreakpoint(dataBreakpointInfoResponse.description, dataBreakpointInfoResponse.dataId!, !!dataBreakpointInfoResponse.canPersist, dataBreakpointInfoResponse.accessTypes, 'write', undefined);
|
||||
await debugService.addDataBreakpoint({ description: dataBreakpointInfoResponse.description, src: { type: DataBreakpointSetType.Variable, dataId: dataBreakpointInfoResponse.dataId! }, canPersist: !!dataBreakpointInfoResponse.canPersist, accessTypes: dataBreakpointInfoResponse.accessTypes, accessType: 'write' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -777,7 +777,7 @@ CommandsRegistry.registerCommand({
|
|||
handler: async (accessor: ServicesAccessor) => {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
if (dataBreakpointInfoResponse) {
|
||||
await debugService.addDataBreakpoint(dataBreakpointInfoResponse.description, dataBreakpointInfoResponse.dataId!, !!dataBreakpointInfoResponse.canPersist, dataBreakpointInfoResponse.accessTypes, 'readWrite', undefined);
|
||||
await debugService.addDataBreakpoint({ description: dataBreakpointInfoResponse.description, src: { type: DataBreakpointSetType.Variable, dataId: dataBreakpointInfoResponse.dataId! }, canPersist: !!dataBreakpointInfoResponse.canPersist, accessTypes: dataBreakpointInfoResponse.accessTypes, accessType: 'readWrite' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -788,7 +788,7 @@ CommandsRegistry.registerCommand({
|
|||
handler: async (accessor: ServicesAccessor) => {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
if (dataBreakpointInfoResponse) {
|
||||
await debugService.addDataBreakpoint(dataBreakpointInfoResponse.description, dataBreakpointInfoResponse.dataId!, !!dataBreakpointInfoResponse.canPersist, dataBreakpointInfoResponse.accessTypes, 'read', undefined);
|
||||
await debugService.addDataBreakpoint({ description: dataBreakpointInfoResponse.description, src: { type: DataBreakpointSetType.Variable, dataId: dataBreakpointInfoResponse.dataId! }, canPersist: !!dataBreakpointInfoResponse.canPersist, accessTypes: dataBreakpointInfoResponse.accessTypes, accessType: 'read' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ import { ITelemetryEndpoint } from 'vs/platform/telemetry/common/telemetry';
|
|||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { DebugCompoundRoot } from 'vs/workbench/contrib/debug/common/debugCompoundRoot';
|
||||
import { IInstructionBreakpointOptions } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { IDataBreakpointOptions, IInstructionBreakpointOptions } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
import { ITaskIdentifier } from 'vs/workbench/contrib/tasks/common/tasks';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
@ -62,6 +62,7 @@ export const CONTEXT_CALLSTACK_SESSION_HAS_ONE_THREAD = new RawContextKey<boolea
|
|||
export const CONTEXT_WATCH_ITEM_TYPE = new RawContextKey<string>('watchItemType', undefined, { type: 'string', description: nls.localize('watchItemType', "Represents the item type of the focused element in the WATCH view. For example: 'expression', 'variable'") });
|
||||
export const CONTEXT_CAN_VIEW_MEMORY = new RawContextKey<boolean>('canViewMemory', undefined, { type: 'boolean', description: nls.localize('canViewMemory', "Indicates whether the item in the view has an associated memory refrence.") });
|
||||
export const CONTEXT_BREAKPOINT_ITEM_TYPE = new RawContextKey<string>('breakpointItemType', undefined, { type: 'string', description: nls.localize('breakpointItemType', "Represents the item type of the focused element in the BREAKPOINTS view. For example: 'breakpoint', 'exceptionBreakppint', 'functionBreakpoint', 'dataBreakpoint'") });
|
||||
export const CONTEXT_BREAKPOINT_ITEM_IS_DATA_BYTES = new RawContextKey<boolean>('breakpointItemBytes', undefined, { type: 'boolean', description: nls.localize('breakpointItemIsDataBytes', "Whether the breakpoint item is a data breakpoint on a byte range.") });
|
||||
export const CONTEXT_BREAKPOINT_HAS_MODES = new RawContextKey<boolean>('breakpointHasModes', false, { type: 'boolean', description: nls.localize('breakpointHasModes', "Whether the breakpoint has multiple modes it can switch to.") });
|
||||
export const CONTEXT_BREAKPOINT_SUPPORTS_CONDITION = new RawContextKey<boolean>('breakpointSupportsCondition', false, { type: 'boolean', description: nls.localize('breakpointSupportsCondition', "True when the focused breakpoint supports conditions.") });
|
||||
export const CONTEXT_LOADED_SCRIPTS_SUPPORTED = new RawContextKey<boolean>('loadedScriptsSupported', false, { type: 'boolean', description: nls.localize('loadedScriptsSupported', "True when the focused sessions supports the LOADED SCRIPTS view") });
|
||||
|
@ -78,6 +79,7 @@ export const CONTEXT_DEBUGGERS_AVAILABLE = new RawContextKey<boolean>('debuggers
|
|||
export const CONTEXT_DEBUG_EXTENSION_AVAILABLE = new RawContextKey<boolean>('debugExtensionAvailable', true, { type: 'boolean', description: nls.localize('debugExtensionsAvailable', "True when there is at least one debug extension installed and enabled.") });
|
||||
export const CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT = new RawContextKey<string>('debugProtocolVariableMenuContext', undefined, { type: 'string', description: nls.localize('debugProtocolVariableMenuContext', "Represents the context the debug adapter sets on the focused variable in the VARIABLES view.") });
|
||||
export const CONTEXT_SET_VARIABLE_SUPPORTED = new RawContextKey<boolean>('debugSetVariableSupported', false, { type: 'boolean', description: nls.localize('debugSetVariableSupported', "True when the focused session supports 'setVariable' request.") });
|
||||
export const CONTEXT_SET_DATA_BREAKPOINT_BYTES_SUPPORTED = new RawContextKey<boolean>('debugSetDataBreakpointAddressSupported', false, { type: 'boolean', description: nls.localize('debugSetDataBreakpointAddressSupported', "True when the focused session supports 'getBreakpointInfo' request on an address.") });
|
||||
export const CONTEXT_SET_EXPRESSION_SUPPORTED = new RawContextKey<boolean>('debugSetExpressionSupported', false, { type: 'boolean', description: nls.localize('debugSetExpressionSupported', "True when the focused session supports 'setExpression' request.") });
|
||||
export const CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED = new RawContextKey<boolean>('breakWhenValueChangesSupported', false, { type: 'boolean', description: nls.localize('breakWhenValueChangesSupported', "True when the focused session supports to break when value changes.") });
|
||||
export const CONTEXT_BREAK_WHEN_VALUE_IS_ACCESSED_SUPPORTED = new RawContextKey<boolean>('breakWhenValueIsAccessedSupported', false, { type: 'boolean', description: nls.localize('breakWhenValueIsAccessedSupported', "True when the focused breakpoint supports to break when value is accessed.") });
|
||||
|
@ -404,6 +406,7 @@ export interface IDebugSession extends ITreeElement {
|
|||
sendBreakpoints(modelUri: uri, bpts: IBreakpoint[], sourceModified: boolean): Promise<void>;
|
||||
sendFunctionBreakpoints(fbps: IFunctionBreakpoint[]): Promise<void>;
|
||||
dataBreakpointInfo(name: string, variablesReference?: number): Promise<IDataBreakpointInfoResponse | undefined>;
|
||||
dataBytesBreakpointInfo(address: string, bytes: number): Promise<IDataBreakpointInfoResponse | undefined>;
|
||||
sendDataBreakpoints(dbps: IDataBreakpoint[]): Promise<void>;
|
||||
sendInstructionBreakpoints(dbps: IInstructionBreakpoint[]): Promise<void>;
|
||||
sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void>;
|
||||
|
@ -607,12 +610,26 @@ export interface IExceptionBreakpoint extends IBaseBreakpoint {
|
|||
readonly description: string | undefined;
|
||||
}
|
||||
|
||||
export const enum DataBreakpointSetType {
|
||||
Variable,
|
||||
Address,
|
||||
}
|
||||
|
||||
/**
|
||||
* Source for a data breakpoint. A data breakpoint on a variable always has a
|
||||
* `dataId` because it cannot reference that variable globally, but addresses
|
||||
* can request info repeated and use session-specific data.
|
||||
*/
|
||||
export type DataBreakpointSource =
|
||||
| { type: DataBreakpointSetType.Variable; dataId: string }
|
||||
| { type: DataBreakpointSetType.Address; address: string; bytes: number };
|
||||
|
||||
export interface IDataBreakpoint extends IBaseBreakpoint {
|
||||
readonly description: string;
|
||||
readonly dataId: string;
|
||||
readonly canPersist: boolean;
|
||||
readonly src: DataBreakpointSource;
|
||||
readonly accessType: DebugProtocol.DataBreakpointAccessType;
|
||||
toDAP(): DebugProtocol.DataBreakpoint;
|
||||
toDAP(session: IDebugSession): Promise<DebugProtocol.DataBreakpoint | undefined>;
|
||||
}
|
||||
|
||||
export interface IInstructionBreakpoint extends IBaseBreakpoint {
|
||||
|
@ -1144,7 +1161,7 @@ export interface IDebugService {
|
|||
/**
|
||||
* Adds a new data breakpoint.
|
||||
*/
|
||||
addDataBreakpoint(label: string, dataId: string, canPersist: boolean, accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined, accessType: DebugProtocol.DataBreakpointAccessType, mode: string | undefined): Promise<void>;
|
||||
addDataBreakpoint(opts: IDataBreakpointOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Updates an already existing data breakpoint.
|
||||
|
|
|
@ -22,7 +22,7 @@ import * as nls from 'vs/nls';
|
|||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
import { IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { DEBUG_MEMORY_SCHEME, DebugTreeItemCollapsibleState, IBaseBreakpoint, IBreakpoint, IBreakpointData, IBreakpointUpdateData, IBreakpointsChangeEvent, IDataBreakpoint, IDebugModel, IDebugSession, IDebugVisualizationTreeItem, IEnablement, IExceptionBreakpoint, IExceptionInfo, IExpression, IExpressionContainer, IFunctionBreakpoint, IInstructionBreakpoint, IMemoryInvalidationEvent, IMemoryRegion, IRawModelUpdate, IRawStoppedDetails, IScope, IStackFrame, IThread, ITreeElement, MemoryRange, MemoryRangeType, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { DEBUG_MEMORY_SCHEME, DataBreakpointSetType, DataBreakpointSource, DebugTreeItemCollapsibleState, IBaseBreakpoint, IBreakpoint, IBreakpointData, IBreakpointUpdateData, IBreakpointsChangeEvent, IDataBreakpoint, IDebugModel, IDebugSession, IDebugVisualizationTreeItem, IEnablement, IExceptionBreakpoint, IExceptionInfo, IExpression, IExpressionContainer, IFunctionBreakpoint, IInstructionBreakpoint, IMemoryInvalidationEvent, IMemoryRegion, IRawModelUpdate, IRawStoppedDetails, IScope, IStackFrame, IThread, ITreeElement, MemoryRange, MemoryRangeType, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Source, UNKNOWN_SOURCE_LABEL, getUriFromSource } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
import { DebugStorage } from 'vs/workbench/contrib/debug/common/debugStorage';
|
||||
import { IDebugVisualizerService } from 'vs/workbench/contrib/debug/common/debugVisualizers';
|
||||
|
@ -1150,15 +1150,18 @@ export class FunctionBreakpoint extends BaseBreakpoint implements IFunctionBreak
|
|||
|
||||
export interface IDataBreakpointOptions extends IBaseBreakpointOptions {
|
||||
description: string;
|
||||
dataId: string;
|
||||
src: DataBreakpointSource;
|
||||
canPersist: boolean;
|
||||
initialSessionData?: { session: IDebugSession; dataId: string };
|
||||
accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined;
|
||||
accessType: DebugProtocol.DataBreakpointAccessType;
|
||||
}
|
||||
|
||||
export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint {
|
||||
private readonly sessionDataIdForAddr = new WeakMap<IDebugSession, string | null>();
|
||||
|
||||
public readonly description: string;
|
||||
public readonly dataId: string;
|
||||
public readonly src: DataBreakpointSource;
|
||||
public readonly canPersist: boolean;
|
||||
public readonly accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined;
|
||||
public readonly accessType: DebugProtocol.DataBreakpointAccessType;
|
||||
|
@ -1169,15 +1172,36 @@ export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint {
|
|||
) {
|
||||
super(id, opts);
|
||||
this.description = opts.description;
|
||||
this.dataId = opts.dataId;
|
||||
if ('dataId' in opts) { // back compat with old saved variables in 1.87
|
||||
opts.src = { type: DataBreakpointSetType.Variable, dataId: opts.dataId as string };
|
||||
}
|
||||
this.src = opts.src;
|
||||
this.canPersist = opts.canPersist;
|
||||
this.accessTypes = opts.accessTypes;
|
||||
this.accessType = opts.accessType;
|
||||
if (opts.initialSessionData) {
|
||||
this.sessionDataIdForAddr.set(opts.initialSessionData.session, opts.initialSessionData.dataId);
|
||||
}
|
||||
}
|
||||
|
||||
toDAP(): DebugProtocol.DataBreakpoint {
|
||||
async toDAP(session: IDebugSession): Promise<DebugProtocol.DataBreakpoint | undefined> {
|
||||
let dataId: string;
|
||||
if (this.src.type === DataBreakpointSetType.Variable) {
|
||||
dataId = this.src.dataId;
|
||||
} else {
|
||||
let sessionDataId = this.sessionDataIdForAddr.get(session);
|
||||
if (!sessionDataId) {
|
||||
sessionDataId = (await session.dataBytesBreakpointInfo(this.src.address, this.src.bytes))?.dataId;
|
||||
if (!sessionDataId) {
|
||||
return undefined;
|
||||
}
|
||||
this.sessionDataIdForAddr.set(session, sessionDataId);
|
||||
}
|
||||
dataId = sessionDataId;
|
||||
}
|
||||
|
||||
return {
|
||||
dataId: this.dataId,
|
||||
dataId,
|
||||
accessType: this.accessType,
|
||||
condition: this.condition,
|
||||
hitCondition: this.hitCondition,
|
||||
|
@ -1188,7 +1212,7 @@ export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint {
|
|||
return {
|
||||
...super.toJSON(),
|
||||
description: this.description,
|
||||
dataId: this.dataId,
|
||||
src: this.src,
|
||||
accessTypes: this.accessTypes,
|
||||
accessType: this.accessType,
|
||||
canPersist: this.canPersist,
|
||||
|
|
|
@ -813,11 +813,22 @@ declare module DebugProtocol {
|
|||
/** Reference to the variable container if the data breakpoint is requested for a child of the container. The `variablesReference` must have been obtained in the current suspended state. See 'Lifetime of Object References' in the Overview section for details. */
|
||||
variablesReference?: number;
|
||||
/** The name of the variable's child to obtain data breakpoint information for.
|
||||
If `variablesReference` isn't specified, this can be an expression.
|
||||
If `variablesReference` isn't specified, this can be an expression, or an address if `asAddress` is also true.
|
||||
*/
|
||||
name: string;
|
||||
/** When `name` is an expression, evaluate it in the scope of this stack frame. If not specified, the expression is evaluated in the global scope. When `variablesReference` is specified, this property has no effect. */
|
||||
frameId?: number;
|
||||
/** If specified, a debug adapter should return information for the range of memory extending `bytes` number of bytes from the address or variable specified by `name`. Breakpoints set using the resulting data ID should pause on data access anywhere within that range.
|
||||
|
||||
Clients may set this property only if the `supportsDataBreakpointBytes` capability is true.
|
||||
*/
|
||||
bytes?: number;
|
||||
/** If `true`, the `name` is a memory address and the debugger should interpret it as a decimal value, or hex value if it is prefixed with `0x`.
|
||||
|
||||
Clients may set this property only if the `supportsDataBreakpointBytes`
|
||||
capability is true.
|
||||
*/
|
||||
asAddress?: boolean;
|
||||
/** The mode of the desired breakpoint. If defined, this must be one of the `breakpointModes` the debug adapter advertised in its `Capabilities`. */
|
||||
mode?: string;
|
||||
}
|
||||
|
@ -1680,42 +1691,6 @@ declare module DebugProtocol {
|
|||
};
|
||||
}
|
||||
|
||||
/** DataAddressBreakpointInfo request; value of command field is 'DataAddressBreakpointInfo'.
|
||||
Obtains information on a possible data breakpoint that could be set on a memory address or memory address range.
|
||||
|
||||
Clients should only call this request if the corresponding capability `supportsDataAddressInfo` is true.
|
||||
*/
|
||||
interface DataAddressBreakpointInfoRequest extends Request {
|
||||
// command: 'DataAddressBreakpointInfo';
|
||||
arguments: DataAddressBreakpointInfoArguments;
|
||||
}
|
||||
|
||||
/** Arguments for `dataAddressBreakpointInfo` request. */
|
||||
interface DataAddressBreakpointInfoArguments {
|
||||
/** The address of the data for which to obtain breakpoint information.
|
||||
Treated as a hex value if prefixed with `0x`, or as a decimal value otherwise.
|
||||
*/
|
||||
address?: string;
|
||||
/** If passed, requests breakpoint information for an exclusive byte range rather than a single address. The range extends the given number of `bytes` from the start `address`.
|
||||
Treated as a hex value if prefixed with `0x`, or as a decimal value otherwise.
|
||||
*/
|
||||
bytes?: string;
|
||||
}
|
||||
|
||||
/** Response to `dataAddressBreakpointInfo` request. */
|
||||
interface DataAddressBreakpointInfoResponse extends Response {
|
||||
body: {
|
||||
/** An identifier for the data on which a data breakpoint can be registered with the `setDataBreakpoints` request or null if no data breakpoint is available. If a `variablesReference` or `frameId` is passed, the `dataId` is valid in the current suspended state, otherwise it's valid indefinitely. See 'Lifetime of Object References' in the Overview section for details. Breakpoints set using the `dataId` in the `setDataBreakpoints` request may outlive the lifetime of the associated `dataId`. */
|
||||
dataId: string | null;
|
||||
/** UI string that describes on what data the breakpoint is set on or why a data breakpoint is not available. */
|
||||
description: string;
|
||||
/** Attribute lists the available access types for a potential data breakpoint. A UI client could surface this information. */
|
||||
accessTypes?: DataBreakpointAccessType[];
|
||||
/** Attribute indicates that a potential data breakpoint could be persisted across sessions. */
|
||||
canPersist?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
/** Information about the capabilities of a debug adapter. */
|
||||
interface Capabilities {
|
||||
/** The debug adapter supports the `configurationDone` request. */
|
||||
|
@ -1788,8 +1763,6 @@ declare module DebugProtocol {
|
|||
supportsBreakpointLocationsRequest?: boolean;
|
||||
/** The debug adapter supports the `clipboard` context value in the `evaluate` request. */
|
||||
supportsClipboardContext?: boolean;
|
||||
/** The debug adapter supports the `dataAddressBreakpointInfo` request. */
|
||||
supportsDataAddressInfo?: boolean;
|
||||
/** The debug adapter supports stepping granularities (argument `granularity`) for the stepping requests. */
|
||||
supportsSteppingGranularity?: boolean;
|
||||
/** The debug adapter supports adding breakpoints based on instruction references. */
|
||||
|
@ -1798,6 +1771,8 @@ declare module DebugProtocol {
|
|||
supportsExceptionFilterOptions?: boolean;
|
||||
/** The debug adapter supports the `singleThread` property on the execution requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`, `stepBack`). */
|
||||
supportsSingleThreadExecutionRequests?: boolean;
|
||||
/** The debug adapter supports the `asAddress` and `bytes` fields in the `dataBreakpointInfo` request. */
|
||||
supportsDataBreakpointBytes?: boolean;
|
||||
/** Modes of breakpoints supported by the debug adapter, such as 'hardware' or 'software'. If present, the client may allow the user to select a mode and include it in its `setBreakpoints` request.
|
||||
|
||||
Clients may present the first applicable mode in this array as the 'default' mode in gestures that set breakpoints.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { CONTEXT_DISASSEMBLE_REQUEST_SUPPORTED, CONTEXT_EXPRESSION_SELECTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_FOCUSED_SESSION_IS_NO_DEBUG, CONTEXT_FOCUSED_STACK_FRAME_HAS_INSTRUCTION_POINTER_REFERENCE, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_SET_EXPRESSION_SUPPORTED, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, IDebugSession, IExpression, IExpressionContainer, IStackFrame, IThread, IViewModel } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { CONTEXT_DISASSEMBLE_REQUEST_SUPPORTED, CONTEXT_EXPRESSION_SELECTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_FOCUSED_SESSION_IS_NO_DEBUG, CONTEXT_FOCUSED_STACK_FRAME_HAS_INSTRUCTION_POINTER_REFERENCE, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_MULTI_SESSION_DEBUG, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_SET_DATA_BREAKPOINT_BYTES_SUPPORTED, CONTEXT_SET_EXPRESSION_SUPPORTED, CONTEXT_SET_VARIABLE_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, IDebugSession, IExpression, IExpressionContainer, IStackFrame, IThread, IViewModel } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
|
||||
export class ViewModel implements IViewModel {
|
||||
|
@ -34,6 +34,7 @@ export class ViewModel implements IViewModel {
|
|||
private stepIntoTargetsSupported!: IContextKey<boolean>;
|
||||
private jumpToCursorSupported!: IContextKey<boolean>;
|
||||
private setVariableSupported!: IContextKey<boolean>;
|
||||
private setDataBreakpointAtByteSupported!: IContextKey<boolean>;
|
||||
private setExpressionSupported!: IContextKey<boolean>;
|
||||
private multiSessionDebug!: IContextKey<boolean>;
|
||||
private terminateDebuggeeSupported!: IContextKey<boolean>;
|
||||
|
@ -52,6 +53,7 @@ export class ViewModel implements IViewModel {
|
|||
this.stepIntoTargetsSupported = CONTEXT_STEP_INTO_TARGETS_SUPPORTED.bindTo(contextKeyService);
|
||||
this.jumpToCursorSupported = CONTEXT_JUMP_TO_CURSOR_SUPPORTED.bindTo(contextKeyService);
|
||||
this.setVariableSupported = CONTEXT_SET_VARIABLE_SUPPORTED.bindTo(contextKeyService);
|
||||
this.setDataBreakpointAtByteSupported = CONTEXT_SET_DATA_BREAKPOINT_BYTES_SUPPORTED.bindTo(contextKeyService);
|
||||
this.setExpressionSupported = CONTEXT_SET_EXPRESSION_SUPPORTED.bindTo(contextKeyService);
|
||||
this.multiSessionDebug = CONTEXT_MULTI_SESSION_DEBUG.bindTo(contextKeyService);
|
||||
this.terminateDebuggeeSupported = CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED.bindTo(contextKeyService);
|
||||
|
@ -88,15 +90,16 @@ export class ViewModel implements IViewModel {
|
|||
this._focusedSession = session;
|
||||
|
||||
this.contextKeyService.bufferChangeEvents(() => {
|
||||
this.loadedScriptsSupportedContextKey.set(session ? !!session.capabilities.supportsLoadedSourcesRequest : false);
|
||||
this.stepBackSupportedContextKey.set(session ? !!session.capabilities.supportsStepBack : false);
|
||||
this.restartFrameSupportedContextKey.set(session ? !!session.capabilities.supportsRestartFrame : false);
|
||||
this.stepIntoTargetsSupported.set(session ? !!session.capabilities.supportsStepInTargetsRequest : false);
|
||||
this.jumpToCursorSupported.set(session ? !!session.capabilities.supportsGotoTargetsRequest : false);
|
||||
this.setVariableSupported.set(session ? !!session.capabilities.supportsSetVariable : false);
|
||||
this.setExpressionSupported.set(session ? !!session.capabilities.supportsSetExpression : false);
|
||||
this.terminateDebuggeeSupported.set(session ? !!session.capabilities.supportTerminateDebuggee : false);
|
||||
this.suspendDebuggeeSupported.set(session ? !!session.capabilities.supportSuspendDebuggee : false);
|
||||
this.loadedScriptsSupportedContextKey.set(!!session?.capabilities.supportsLoadedSourcesRequest);
|
||||
this.stepBackSupportedContextKey.set(!!session?.capabilities.supportsStepBack);
|
||||
this.restartFrameSupportedContextKey.set(!!session?.capabilities.supportsRestartFrame);
|
||||
this.stepIntoTargetsSupported.set(!!session?.capabilities.supportsStepInTargetsRequest);
|
||||
this.jumpToCursorSupported.set(!!session?.capabilities.supportsGotoTargetsRequest);
|
||||
this.setVariableSupported.set(!!session?.capabilities.supportsSetVariable);
|
||||
this.setDataBreakpointAtByteSupported.set(!!session?.capabilities.supportsDataBreakpointBytes);
|
||||
this.setExpressionSupported.set(!!session?.capabilities.supportsSetExpression);
|
||||
this.terminateDebuggeeSupported.set(!!session?.capabilities.supportTerminateDebuggee);
|
||||
this.suspendDebuggeeSupported.set(!!session?.capabilities.supportSuspendDebuggee);
|
||||
this.disassembleRequestSupported.set(!!session?.capabilities.supportsDisassembleRequest);
|
||||
this.focusedStackFrameHasInstructionPointerReference.set(!!stackFrame?.instructionPointerReference);
|
||||
const attach = !!session && isSessionAttach(session);
|
||||
|
|
|
@ -19,7 +19,7 @@ import { NullLogService } from 'vs/platform/log/common/log';
|
|||
import { StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { createBreakpointDecorations } from 'vs/workbench/contrib/debug/browser/breakpointEditorContribution';
|
||||
import { getBreakpointMessageAndIcon, getExpandedBodySize } from 'vs/workbench/contrib/debug/browser/breakpointsView';
|
||||
import { IBreakpointData, IBreakpointUpdateData, IDebugService, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { DataBreakpointSetType, IBreakpointData, IBreakpointUpdateData, IDebugService, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Breakpoint, DebugModel } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { createTestSession } from 'vs/workbench/contrib/debug/test/browser/callStack.test';
|
||||
import { createMockDebugModel, mockUriIdentityService } from 'vs/workbench/contrib/debug/test/browser/mockDebugModel';
|
||||
|
@ -313,13 +313,13 @@ suite('Debug - Breakpoints', () => {
|
|||
let eventCount = 0;
|
||||
disposables.add(model.onDidChangeBreakpoints(() => eventCount++));
|
||||
|
||||
model.addDataBreakpoint({ description: 'label', dataId: 'id', canPersist: true, accessTypes: ['read'], accessType: 'read' }, '1');
|
||||
model.addDataBreakpoint({ description: 'second', dataId: 'secondId', canPersist: false, accessTypes: ['readWrite'], accessType: 'readWrite' }, '2');
|
||||
model.addDataBreakpoint({ description: 'label', src: { type: DataBreakpointSetType.Variable, dataId: 'id' }, canPersist: true, accessTypes: ['read'], accessType: 'read' }, '1');
|
||||
model.addDataBreakpoint({ description: 'second', src: { type: DataBreakpointSetType.Variable, dataId: 'secondId' }, canPersist: false, accessTypes: ['readWrite'], accessType: 'readWrite' }, '2');
|
||||
model.updateDataBreakpoint('1', { condition: 'aCondition' });
|
||||
model.updateDataBreakpoint('2', { hitCondition: '10' });
|
||||
const dataBreakpoints = model.getDataBreakpoints();
|
||||
assert.strictEqual(dataBreakpoints[0].canPersist, true);
|
||||
assert.strictEqual(dataBreakpoints[0].dataId, 'id');
|
||||
assert.deepStrictEqual(dataBreakpoints[0].src, { type: DataBreakpointSetType.Variable, dataId: 'id' });
|
||||
assert.strictEqual(dataBreakpoints[0].accessType, 'read');
|
||||
assert.strictEqual(dataBreakpoints[0].condition, 'aCondition');
|
||||
assert.strictEqual(dataBreakpoints[1].canPersist, false);
|
||||
|
@ -374,7 +374,7 @@ suite('Debug - Breakpoints', () => {
|
|||
assert.strictEqual(result.message, 'Disabled Logpoint');
|
||||
assert.strictEqual(result.icon.id, 'debug-breakpoint-log-disabled');
|
||||
|
||||
model.addDataBreakpoint({ description: 'label', canPersist: true, accessTypes: ['read'], accessType: 'read', dataId: 'id' });
|
||||
model.addDataBreakpoint({ description: 'label', canPersist: true, accessTypes: ['read'], accessType: 'read', src: { type: DataBreakpointSetType.Variable, dataId: 'id' } });
|
||||
const dataBreakpoints = model.getDataBreakpoints();
|
||||
result = getBreakpointMessageAndIcon(State.Stopped, true, dataBreakpoints[0], ls, model);
|
||||
assert.strictEqual(result.message, 'Data Breakpoint');
|
||||
|
|
|
@ -13,7 +13,7 @@ import { NullLogService } from 'vs/platform/log/common/log';
|
|||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
|
||||
import { AdapterEndEvent, IAdapterManager, IBreakpoint, IBreakpointData, IBreakpointUpdateData, IConfig, IConfigurationManager, IDataBreakpoint, IDebugModel, IDebugService, IDebugSession, IDebugSessionOptions, IDebugger, IExceptionBreakpoint, IExceptionInfo, IFunctionBreakpoint, IInstructionBreakpoint, ILaunch, IMemoryRegion, INewReplElementData, IRawModelUpdate, IRawStoppedDetails, IReplElement, IStackFrame, IThread, IViewModel, LoadedSourceEvent, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { AdapterEndEvent, IAdapterManager, IBreakpoint, IBreakpointData, IBreakpointUpdateData, IConfig, IConfigurationManager, IDataBreakpoint, IDataBreakpointInfoResponse, IDebugModel, IDebugService, IDebugSession, IDebugSessionOptions, IDebugger, IExceptionBreakpoint, IExceptionInfo, IFunctionBreakpoint, IInstructionBreakpoint, ILaunch, IMemoryRegion, INewReplElementData, IRawModelUpdate, IRawStoppedDetails, IReplElement, IStackFrame, IThread, IViewModel, LoadedSourceEvent, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { DebugCompoundRoot } from 'vs/workbench/contrib/debug/common/debugCompoundRoot';
|
||||
import { IInstructionBreakpointOptions } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
|
@ -114,7 +114,7 @@ export class MockDebugService implements IDebugService {
|
|||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
addDataBreakpoint(label: string, dataId: string, canPersist: boolean): Promise<void> {
|
||||
addDataBreakpoint(): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
|
@ -223,6 +223,10 @@ export class MockSession implements IDebugSession {
|
|||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
dataBytesBreakpointInfo(address: string, bytes: number): Promise<IDataBreakpointInfoResponse | undefined> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
dataBreakpointInfo(name: string, variablesReference?: number | undefined): Promise<{ dataId: string | null; description: string; canPersist?: boolean | undefined } | undefined> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue