mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-07 09:35:41 -05:00
VSCode merge (#4610)
* Merge from vscode e388c734f30757875976c7e326d6cfeee77710de * fix yarn lcoks * remove small issue
This commit is contained in:
@@ -15,10 +15,8 @@ import { MenuId, IMenu, IMenuService } from 'vs/platform/actions/common/actions'
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { renderViewTree } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { RestartAction, StopAction, ContinueAction, StepOverAction, StepIntoAction, StepOutAction, PauseAction, RestartFrameAction, TerminateThreadAction, CopyStackTraceAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IViewletPanelOptions, ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
@@ -264,32 +262,13 @@ export class CallStackView extends ViewletPanel {
|
||||
}
|
||||
|
||||
private onContextMenu(e: ITreeContextMenuEvent<CallStackItem>): void {
|
||||
const actions: IAction[] = [];
|
||||
const element = e.element;
|
||||
if (isDebugSession(element)) {
|
||||
this.callStackItemType.set('session');
|
||||
actions.push(this.instantiationService.createInstance(RestartAction, RestartAction.ID, RestartAction.LABEL));
|
||||
actions.push(new StopAction(StopAction.ID, StopAction.LABEL, this.debugService, this.keybindingService));
|
||||
} else if (element instanceof Thread) {
|
||||
this.callStackItemType.set('thread');
|
||||
const thread = <Thread>element;
|
||||
if (thread.stopped) {
|
||||
actions.push(new ContinueAction(ContinueAction.ID, ContinueAction.LABEL, this.debugService, this.keybindingService));
|
||||
actions.push(new StepOverAction(StepOverAction.ID, StepOverAction.LABEL, this.debugService, this.keybindingService));
|
||||
actions.push(new StepIntoAction(StepIntoAction.ID, StepIntoAction.LABEL, this.debugService, this.keybindingService));
|
||||
actions.push(new StepOutAction(StepOutAction.ID, StepOutAction.LABEL, this.debugService, this.keybindingService));
|
||||
} else {
|
||||
actions.push(new PauseAction(PauseAction.ID, PauseAction.LABEL, this.debugService, this.keybindingService));
|
||||
}
|
||||
|
||||
actions.push(new Separator());
|
||||
actions.push(new TerminateThreadAction(TerminateThreadAction.ID, TerminateThreadAction.LABEL, this.debugService, this.keybindingService));
|
||||
} else if (element instanceof StackFrame) {
|
||||
this.callStackItemType.set('stackFrame');
|
||||
if (element.thread.session.capabilities.supportsRestartFrame) {
|
||||
actions.push(new RestartFrameAction(RestartFrameAction.ID, RestartFrameAction.LABEL, this.debugService, this.keybindingService));
|
||||
}
|
||||
actions.push(this.instantiationService.createInstance(CopyStackTraceAction, CopyStackTraceAction.ID, CopyStackTraceAction.LABEL));
|
||||
} else {
|
||||
this.callStackItemType.reset();
|
||||
}
|
||||
@@ -297,7 +276,8 @@ export class CallStackView extends ViewletPanel {
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
getActions: () => {
|
||||
fillInContextMenuActions(this.contributedContextMenu, { arg: this.getContextForContributedActions(element) }, actions, this.contextMenuService);
|
||||
const actions: IAction[] = [];
|
||||
fillInContextMenuActions(this.contributedContextMenu, { arg: this.getContextForContributedActions(element), shouldForwardArgs: true }, actions, this.contextMenuService);
|
||||
return actions;
|
||||
},
|
||||
getActionsContext: () => element
|
||||
@@ -315,6 +295,9 @@ export class CallStackView extends ViewletPanel {
|
||||
if (element instanceof Thread) {
|
||||
return element.threadId;
|
||||
}
|
||||
if (isDebugSession(element)) {
|
||||
return element.getId();
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IListService } from 'vs/platform/list/browser/listService';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED, IConfig } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Expression, Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED, IConfig, IStackFrame, IThread, IDebugSession, CONTEXT_DEBUG_STATE, REPL_ID } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Expression, Variable, Breakpoint, FunctionBreakpoint, Thread } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { ICodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
@@ -25,12 +25,188 @@ import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { PanelFocusContext } from 'vs/workbench/common/panel';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { startDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
|
||||
export const ADD_CONFIGURATION_ID = 'debug.addConfiguration';
|
||||
export const TOGGLE_INLINE_BREAKPOINT_ID = 'editor.debug.action.toggleInlineBreakpoint';
|
||||
export const COPY_STACK_TRACE_ID = 'debug.copyStackTrace';
|
||||
export const REVERSE_CONTINUE_ID = 'workbench.action.debug.reverseContinue';
|
||||
export const STEP_BACK_ID = 'workbench.action.debug.stepBack';
|
||||
export const RESTART_SESSION_ID = 'workbench.action.debug.restart';
|
||||
export const TERMINATE_THREAD_ID = 'workbench.action.debug.terminateThread';
|
||||
export const STEP_OVER_ID = 'workbench.action.debug.stepOver';
|
||||
export const STEP_INTO_ID = 'workbench.action.debug.stepInto';
|
||||
export const STEP_OUT_ID = 'workbench.action.debug.stepOut';
|
||||
export const PAUSE_ID = 'workbench.action.debug.pause';
|
||||
export const DISCONNECT_ID = 'workbench.action.debug.disconnect';
|
||||
export const STOP_ID = 'workbench.action.debug.stop';
|
||||
export const RESTART_FRAME_ID = 'workbench.action.debug.restartFrame';
|
||||
export const CONTINUE_ID = 'workbench.action.debug.continue';
|
||||
export const FOCUS_REPL_ID = 'workbench.debug.action.focusRepl';
|
||||
|
||||
function getThreadAndRun(accessor: ServicesAccessor, thread: IThread | undefined, run: (thread: IThread) => Promise<void>, ): void {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
if (!(thread instanceof Thread)) {
|
||||
thread = debugService.getViewModel().focusedThread;
|
||||
}
|
||||
|
||||
if (thread) {
|
||||
run(thread).then(undefined, onUnexpectedError);
|
||||
}
|
||||
}
|
||||
|
||||
export function registerCommands(): void {
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: COPY_STACK_TRACE_ID,
|
||||
handler: (accessor: ServicesAccessor, _: string, frame: IStackFrame) => {
|
||||
const textResourcePropertiesService = accessor.get(ITextResourcePropertiesService);
|
||||
const clipboardService = accessor.get(IClipboardService);
|
||||
const eol = textResourcePropertiesService.getEOL(frame.source.uri);
|
||||
clipboardService.writeText(frame.thread.getCallStack().map(sf => sf.toString()).join(eol));
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: REVERSE_CONTINUE_ID,
|
||||
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
|
||||
getThreadAndRun(accessor, thread, thread => thread.reverseContinue());
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: STEP_BACK_ID,
|
||||
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
|
||||
getThreadAndRun(accessor, thread, thread => thread.stepBack());
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: TERMINATE_THREAD_ID,
|
||||
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
|
||||
getThreadAndRun(accessor, thread, thread => thread.terminate());
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: RESTART_SESSION_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.F5,
|
||||
when: CONTEXT_IN_DEBUG_MODE,
|
||||
handler: (accessor: ServicesAccessor, _: string, session: IDebugSession | undefined) => {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
if (!session || !session.getId) {
|
||||
session = debugService.getViewModel().focusedSession;
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
const historyService = accessor.get(IHistoryService);
|
||||
startDebugging(debugService, historyService, false);
|
||||
} else {
|
||||
session.removeReplExpressions();
|
||||
debugService.restartSession(session).then(undefined, onUnexpectedError);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: STEP_OVER_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyCode.F10,
|
||||
when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'),
|
||||
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
|
||||
getThreadAndRun(accessor, thread, thread => thread.next());
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: STEP_INTO_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyCode.F11,
|
||||
when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'),
|
||||
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
|
||||
getThreadAndRun(accessor, thread, thread => thread.stepIn());
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: STEP_OUT_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyMod.Shift | KeyCode.F11,
|
||||
when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'),
|
||||
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
|
||||
getThreadAndRun(accessor, thread, thread => thread.stepOut());
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: PAUSE_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyCode.F6,
|
||||
when: CONTEXT_DEBUG_STATE.isEqualTo('running'),
|
||||
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
|
||||
getThreadAndRun(accessor, thread, thread => thread.pause());
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: DISCONNECT_ID,
|
||||
handler: (accessor: ServicesAccessor) => {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
const session = debugService.getViewModel().focusedSession;
|
||||
debugService.stopSession(session).then(undefined, onUnexpectedError);
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: STOP_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyMod.Shift | KeyCode.F5,
|
||||
when: CONTEXT_IN_DEBUG_MODE,
|
||||
handler: (accessor: ServicesAccessor, _: string, session: IDebugSession | undefined) => {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
if (!session || !session.getId) {
|
||||
session = debugService.getViewModel().focusedSession;
|
||||
}
|
||||
|
||||
debugService.stopSession(session).then(undefined, onUnexpectedError);
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: RESTART_FRAME_ID,
|
||||
handler: (accessor: ServicesAccessor, _: string, frame: IStackFrame | undefined) => {
|
||||
const debugService = accessor.get(IDebugService);
|
||||
if (!frame) {
|
||||
frame = debugService.getViewModel().focusedStackFrame;
|
||||
}
|
||||
|
||||
return frame!.restart();
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: CONTINUE_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyCode.F5,
|
||||
when: CONTEXT_IN_DEBUG_MODE,
|
||||
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
|
||||
getThreadAndRun(accessor, thread, thread => thread.continue());
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: FOCUS_REPL_ID,
|
||||
handler: (accessor) => {
|
||||
const panelService = accessor.get(IPanelService);
|
||||
panelService.openPanel(REPL_ID, true);
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: 'debug.startFromConfig',
|
||||
handler: (accessor, config: IConfig) => {
|
||||
|
||||
@@ -9,8 +9,8 @@ import { IAction } from 'vs/base/common/actions';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||
import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { StartAction, ToggleReplAction, ConfigureAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration, REPL_ID } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { StartAction, ConfigureAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { StartDebugActionItem, FocusSessionActionItem } from 'vs/workbench/contrib/debug/browser/debugActionItems';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
@@ -31,6 +31,8 @@ import { IMenu, MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { MenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { TogglePanelAction } from 'vs/workbench/browser/panel';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
|
||||
export class DebugViewlet extends ViewContainerViewlet {
|
||||
|
||||
@@ -193,3 +195,15 @@ export class DebugViewlet extends ViewContainerViewlet {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ToggleReplAction extends TogglePanelAction {
|
||||
static readonly ID = 'debug.toggleRepl';
|
||||
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugConsoleAction' }, 'Debug Console');
|
||||
|
||||
constructor(id: string, label: string,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IPanelService panelService: IPanelService
|
||||
) {
|
||||
super(id, label, REPL_ID, panelService, layoutService, 'debug-action toggle-repl');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ import { renderExpressionValue } from 'vs/workbench/contrib/debug/browser/baseDe
|
||||
import { handleANSIOutput } from 'vs/workbench/contrib/debug/browser/debugANSIHandling';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
|
||||
import { ReplCollapseAllAction, CopyAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { removeAnsiEscapeCodes } from 'vs/base/common/strings';
|
||||
@@ -452,12 +451,19 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
|
||||
|
||||
private onContextMenu(e: ITreeContextMenuEvent<IReplElement>): void {
|
||||
const actions: IAction[] = [];
|
||||
actions.push(new CopyAction(CopyAction.ID, CopyAction.LABEL, this.clipboardService));
|
||||
actions.push(new Action('debug.replCopy', nls.localize('copy', "Copy"), undefined, true, () => {
|
||||
this.clipboardService.writeText(window.getSelection().toString());
|
||||
return Promise.resolve();
|
||||
}));
|
||||
actions.push(new Action('workbench.debug.action.copyAll', nls.localize('copyAll', "Copy All"), undefined, true, () => {
|
||||
this.clipboardService.writeText(this.getVisibleContent());
|
||||
return Promise.resolve(undefined);
|
||||
}));
|
||||
actions.push(new ReplCollapseAllAction(this.tree, this.replInput));
|
||||
actions.push(new Action('debug.collapseRepl', nls.localize('collapse', "Collapse All"), undefined, true, () => {
|
||||
this.tree.collapseAll();
|
||||
this.replInput.focus();
|
||||
return Promise.resolve();
|
||||
}));
|
||||
actions.push(new Separator());
|
||||
actions.push(this.clearReplAction);
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ import { Variable, Scope } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { renderViewTree, renderVariable, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { SetValueAction, AddToWatchExpressionsAction, CopyValueAction, CopyEvaluatePathAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IViewletPanelOptions, ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
|
||||
@@ -27,6 +27,7 @@ import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { FuzzyScore, createMatches } from 'vs/base/common/filters';
|
||||
import { HighlightedLabel, IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
@@ -45,6 +46,7 @@ export class VariablesView extends ViewletPanel {
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IClipboardService private readonly clipboardService: IClipboardService
|
||||
) {
|
||||
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: nls.localize('variablesSection', "Variables Section") }, keybindingService, contextMenuService, configurationService);
|
||||
|
||||
@@ -129,20 +131,33 @@ export class VariablesView extends ViewletPanel {
|
||||
}
|
||||
|
||||
private onContextMenu(e: ITreeContextMenuEvent<IExpression | IScope>): void {
|
||||
const element = e.element;
|
||||
if (element instanceof Variable && !!element.value) {
|
||||
const variable = e.element;
|
||||
if (variable instanceof Variable && !!variable.value) {
|
||||
const actions: IAction[] = [];
|
||||
const variable = element as Variable;
|
||||
actions.push(new SetValueAction(SetValueAction.ID, SetValueAction.LABEL, variable, this.debugService, this.keybindingService));
|
||||
const session = this.debugService.getViewModel().focusedSession;
|
||||
if (session && session.capabilities.supportsSetVariable) {
|
||||
actions.push(new Action('workbench.setValue', nls.localize('setValue', "Set Value"), undefined, true, () => {
|
||||
this.debugService.getViewModel().setSelectedExpression(variable);
|
||||
return Promise.resolve();
|
||||
}));
|
||||
}
|
||||
actions.push(this.instantiationService.createInstance(CopyValueAction, CopyValueAction.ID, CopyValueAction.LABEL, variable, 'variables'));
|
||||
actions.push(this.instantiationService.createInstance(CopyEvaluatePathAction, CopyEvaluatePathAction.ID, CopyEvaluatePathAction.LABEL, variable));
|
||||
actions.push(new Separator());
|
||||
actions.push(new AddToWatchExpressionsAction(AddToWatchExpressionsAction.ID, AddToWatchExpressionsAction.LABEL, variable, this.debugService, this.keybindingService));
|
||||
if (variable.evaluateName) {
|
||||
actions.push(new Action('debug.copyEvaluatePath', nls.localize('copyAsExpression', "Copy as Expression"), undefined, true, () => {
|
||||
this.clipboardService.writeText(variable.evaluateName!);
|
||||
return Promise.resolve();
|
||||
}));
|
||||
actions.push(new Separator());
|
||||
actions.push(new Action('debug.addToWatchExpressions', nls.localize('addToWatchExpressions', "Add to Watch"), undefined, true, () => {
|
||||
this.debugService.addWatchExpression(variable.evaluateName);
|
||||
return Promise.resolve(undefined);
|
||||
}));
|
||||
}
|
||||
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => element
|
||||
getActionsContext: () => variable
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import { CollapseAction } from 'vs/workbench/browser/viewlet';
|
||||
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||
import { IDebugService, IExpression, CONTEXT_WATCH_EXPRESSIONS_FOCUSED } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Expression, Variable } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { AddWatchExpressionAction, RemoveAllWatchExpressionsAction, EditWatchExpressionAction, RemoveWatchExpressionAction, CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { AddWatchExpressionAction, RemoveAllWatchExpressionsAction, CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { renderExpressionValue, renderViewTree, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -144,13 +144,19 @@ export class WatchExpressionsView extends ViewletPanel {
|
||||
if (element instanceof Expression) {
|
||||
const expression = <Expression>element;
|
||||
actions.push(new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService));
|
||||
actions.push(new EditWatchExpressionAction(EditWatchExpressionAction.ID, EditWatchExpressionAction.LABEL, this.debugService, this.keybindingService));
|
||||
actions.push(new Action('debug.editWatchExpression', nls.localize('editWatchExpression', "Edit Expression"), undefined, true, () => {
|
||||
this.debugService.getViewModel().setSelectedExpression(expression);
|
||||
return Promise.resolve();
|
||||
}));
|
||||
if (!expression.hasChildren) {
|
||||
actions.push(this.instantiationService.createInstance(CopyValueAction, CopyValueAction.ID, CopyValueAction.LABEL, expression.value, 'watch', this.debugService));
|
||||
}
|
||||
actions.push(new Separator());
|
||||
|
||||
actions.push(new RemoveWatchExpressionAction(RemoveWatchExpressionAction.ID, RemoveWatchExpressionAction.LABEL, this.debugService, this.keybindingService));
|
||||
actions.push(new Action('debug.removeWatchExpression', nls.localize('removeWatchExpression', "Remove Expression"), undefined, true, () => {
|
||||
this.debugService.removeWatchExpressions(expression.getId());
|
||||
return Promise.resolve();
|
||||
}));
|
||||
actions.push(new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService));
|
||||
} else {
|
||||
actions.push(new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService));
|
||||
|
||||
161
src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts
Normal file
161
src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDebugAdapter } from 'vs/workbench/contrib/debug/common/debug';
|
||||
|
||||
/**
|
||||
* Abstract implementation of the low level API for a debug adapter.
|
||||
* Missing is how this API communicates with the debug adapter.
|
||||
*/
|
||||
export abstract class AbstractDebugAdapter implements IDebugAdapter {
|
||||
|
||||
private sequence: number;
|
||||
private pendingRequests: Map<number, (e: DebugProtocol.Response) => void>;
|
||||
private requestCallback: (request: DebugProtocol.Request) => void;
|
||||
private eventCallback: (request: DebugProtocol.Event) => void;
|
||||
private messageCallback: (message: DebugProtocol.ProtocolMessage) => void;
|
||||
protected readonly _onError: Emitter<Error>;
|
||||
protected readonly _onExit: Emitter<number | null>;
|
||||
|
||||
constructor() {
|
||||
this.sequence = 1;
|
||||
this.pendingRequests = new Map();
|
||||
this._onError = new Emitter<Error>();
|
||||
this._onExit = new Emitter<number>();
|
||||
}
|
||||
|
||||
abstract startSession(): Promise<void>;
|
||||
|
||||
abstract stopSession(): Promise<void>;
|
||||
|
||||
abstract sendMessage(message: DebugProtocol.ProtocolMessage): void;
|
||||
|
||||
get onError(): Event<Error> {
|
||||
return this._onError.event;
|
||||
}
|
||||
|
||||
get onExit(): Event<number | null> {
|
||||
return this._onExit.event;
|
||||
}
|
||||
|
||||
onMessage(callback: (message: DebugProtocol.ProtocolMessage) => void): void {
|
||||
if (this.eventCallback) {
|
||||
this._onError.fire(new Error(`attempt to set more than one 'Message' callback`));
|
||||
}
|
||||
this.messageCallback = callback;
|
||||
}
|
||||
|
||||
onEvent(callback: (event: DebugProtocol.Event) => void): void {
|
||||
if (this.eventCallback) {
|
||||
this._onError.fire(new Error(`attempt to set more than one 'Event' callback`));
|
||||
}
|
||||
this.eventCallback = callback;
|
||||
}
|
||||
|
||||
onRequest(callback: (request: DebugProtocol.Request) => void): void {
|
||||
if (this.requestCallback) {
|
||||
this._onError.fire(new Error(`attempt to set more than one 'Request' callback`));
|
||||
}
|
||||
this.requestCallback = callback;
|
||||
}
|
||||
|
||||
sendResponse(response: DebugProtocol.Response): void {
|
||||
if (response.seq > 0) {
|
||||
this._onError.fire(new Error(`attempt to send more than one response for command ${response.command}`));
|
||||
}
|
||||
else {
|
||||
this.internalSend('response', response);
|
||||
}
|
||||
}
|
||||
|
||||
sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void {
|
||||
const request: any = {
|
||||
command: command
|
||||
};
|
||||
if (args && Object.keys(args).length > 0) {
|
||||
request.arguments = args;
|
||||
}
|
||||
this.internalSend('request', request);
|
||||
if (typeof timeout === 'number') {
|
||||
const timer = setTimeout(() => {
|
||||
clearTimeout(timer);
|
||||
const clb = this.pendingRequests.get(request.seq);
|
||||
if (clb) {
|
||||
this.pendingRequests.delete(request.seq);
|
||||
const err: DebugProtocol.Response = {
|
||||
type: 'response',
|
||||
seq: 0,
|
||||
request_seq: request.seq,
|
||||
success: false,
|
||||
command,
|
||||
message: `timeout after ${timeout} ms`
|
||||
};
|
||||
clb(err);
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
if (clb) {
|
||||
// store callback for this request
|
||||
this.pendingRequests.set(request.seq, clb);
|
||||
}
|
||||
}
|
||||
|
||||
acceptMessage(message: DebugProtocol.ProtocolMessage): void {
|
||||
if (this.messageCallback) {
|
||||
this.messageCallback(message);
|
||||
}
|
||||
else {
|
||||
switch (message.type) {
|
||||
case 'event':
|
||||
if (this.eventCallback) {
|
||||
this.eventCallback(<DebugProtocol.Event>message);
|
||||
}
|
||||
break;
|
||||
case 'request':
|
||||
if (this.requestCallback) {
|
||||
this.requestCallback(<DebugProtocol.Request>message);
|
||||
}
|
||||
break;
|
||||
case 'response':
|
||||
const response = <DebugProtocol.Response>message;
|
||||
const clb = this.pendingRequests.get(response.request_seq);
|
||||
if (clb) {
|
||||
this.pendingRequests.delete(response.request_seq);
|
||||
clb(response);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private internalSend(typ: 'request' | 'response' | 'event', message: DebugProtocol.ProtocolMessage): void {
|
||||
message.type = typ;
|
||||
message.seq = this.sequence++;
|
||||
this.sendMessage(message);
|
||||
}
|
||||
|
||||
protected cancelPending() {
|
||||
const pending = this.pendingRequests;
|
||||
this.pendingRequests = new Map();
|
||||
setTimeout(_ => {
|
||||
pending.forEach((callback, request_seq) => {
|
||||
const err: DebugProtocol.Response = {
|
||||
type: 'response',
|
||||
seq: 0,
|
||||
request_seq,
|
||||
success: false,
|
||||
command: 'canceled',
|
||||
message: 'canceled'
|
||||
};
|
||||
callback(err);
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.cancelPending();
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ export const CONTEXT_LOADED_SCRIPTS_SUPPORTED = new RawContextKey<boolean>('load
|
||||
export const CONTEXT_LOADED_SCRIPTS_ITEM_TYPE = new RawContextKey<string>('loadedScriptsItemType', undefined);
|
||||
export const CONTEXT_FOCUSED_SESSION_IS_ATTACH = new RawContextKey<boolean>('focusedSessionIsAttach', false);
|
||||
export const CONTEXT_STEP_BACK_SUPPORTED = new RawContextKey<boolean>('stepBackSupported', false);
|
||||
export const CONTEXT_RESTART_FRAME_SUPPORTED = new RawContextKey<boolean>('restartFrameSupported', false);
|
||||
|
||||
export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
|
||||
export const DEBUG_SCHEME = 'debug';
|
||||
|
||||
@@ -4,13 +4,32 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { equalsIgnoreCase } from 'vs/base/common/strings';
|
||||
import { IConfig, IDebuggerContribution } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IConfig, IDebuggerContribution, IDebugService } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import { isAbsolute } from 'vs/base/common/path';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { first } from 'vs/base/common/arrays';
|
||||
|
||||
const _formatPIIRegexp = /{([^}]+)}/g;
|
||||
|
||||
export function startDebugging(debugService: IDebugService, historyService: IHistoryService, noDebug: boolean, ): Promise<boolean> {
|
||||
const configurationManager = debugService.getConfigurationManager();
|
||||
let launch = configurationManager.selectedConfiguration.launch;
|
||||
if (!launch || launch.getConfigurationNames().length === 0) {
|
||||
const rootUri = historyService.getLastActiveWorkspaceRoot();
|
||||
launch = configurationManager.getLaunch(rootUri);
|
||||
if (!launch || launch.getConfigurationNames().length === 0) {
|
||||
const launches = configurationManager.getLaunches();
|
||||
launch = first(launches, l => !!(l && l.getConfigurationNames().length), launch);
|
||||
}
|
||||
|
||||
configurationManager.selectConfiguration(launch);
|
||||
}
|
||||
|
||||
return debugService.startDebugging(launch, undefined, noDebug);
|
||||
}
|
||||
|
||||
export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string {
|
||||
return value.replace(_formatPIIRegexp, function (match, group) {
|
||||
if (excludePII && group.length > 0 && group[0] !== '_') {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
|
||||
@@ -26,6 +26,7 @@ export class ViewModel implements IViewModel {
|
||||
private loadedScriptsSupportedContextKey: IContextKey<boolean>;
|
||||
private stepBackSupportedContextKey: IContextKey<boolean>;
|
||||
private focusedSessionIsAttach: IContextKey<boolean>;
|
||||
private restartFrameSupportedContextKey: IContextKey<boolean>;
|
||||
|
||||
constructor(contextKeyService: IContextKeyService) {
|
||||
this._onDidFocusSession = new Emitter<IDebugSession | undefined>();
|
||||
@@ -37,6 +38,7 @@ export class ViewModel implements IViewModel {
|
||||
this.loadedScriptsSupportedContextKey = CONTEXT_LOADED_SCRIPTS_SUPPORTED.bindTo(contextKeyService);
|
||||
this.stepBackSupportedContextKey = CONTEXT_STEP_BACK_SUPPORTED.bindTo(contextKeyService);
|
||||
this.focusedSessionIsAttach = CONTEXT_FOCUSED_SESSION_IS_ATTACH.bindTo(contextKeyService);
|
||||
this.restartFrameSupportedContextKey = CONTEXT_RESTART_FRAME_SUPPORTED.bindTo(contextKeyService);
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
@@ -65,6 +67,7 @@ export class ViewModel implements IViewModel {
|
||||
|
||||
this.loadedScriptsSupportedContextKey.set(session ? !!session.capabilities.supportsLoadedSourcesRequest : false);
|
||||
this.stepBackSupportedContextKey.set(session ? !!session.capabilities.supportsStepBack : false);
|
||||
this.restartFrameSupportedContextKey.set(session ? !!session.capabilities.supportsRestartFrame : false);
|
||||
const attach = !!session && session.configuration.request === 'attach' && !isExtensionHostDebugging(session.configuration);
|
||||
this.focusedSessionIsAttach.set(attach);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { KeybindingWeight, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionRegistryExtensions } from 'vs/workbench/common/actions';
|
||||
import { ShowViewletAction, Extensions as ViewletExtensions, ViewletRegistry, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
|
||||
@@ -22,19 +22,16 @@ import { CallStackView } from 'vs/workbench/contrib/debug/browser/callStackView'
|
||||
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
|
||||
import {
|
||||
IDebugService, VIEWLET_ID, REPL_ID, CONTEXT_IN_DEBUG_MODE, INTERNAL_CONSOLE_OPTIONS_SCHEMA,
|
||||
CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, VIEW_CONTAINER, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED,
|
||||
CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, VIEW_CONTAINER, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED,
|
||||
} from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { DebugEditorModelManager } from 'vs/workbench/contrib/debug/browser/debugEditorModelManager';
|
||||
import {
|
||||
StepOverAction, FocusReplAction, StepIntoAction, StepOutAction, StartAction, RestartAction, ContinueAction, StopAction, DisconnectAction, PauseAction, AddFunctionBreakpointAction,
|
||||
ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction, TerminateThreadAction, StepBackAction, ReverseContinueAction,
|
||||
} from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { StartAction, AddFunctionBreakpointAction, ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { DebugToolbar } from 'vs/workbench/contrib/debug/browser/debugToolbar';
|
||||
import * as service from 'vs/workbench/contrib/debug/electron-browser/debugService';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID } from 'vs/workbench/contrib/debug/browser/debugCommands';
|
||||
import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID } from 'vs/workbench/contrib/debug/browser/debugCommands';
|
||||
import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
|
||||
import { StatusBarColorProvider } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider';
|
||||
import { IViewsRegistry, Extensions as ViewExtensions } from 'vs/workbench/common/views';
|
||||
@@ -119,6 +116,8 @@ viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callSt
|
||||
viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), ctorDescriptor: { ctor: BreakpointsView }, order: 40, weight: 20, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' } }], VIEW_CONTAINER);
|
||||
viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), ctorDescriptor: { ctor: LoadedScriptsView }, order: 35, weight: 5, canToggleVisibility: true, collapsed: true, when: CONTEXT_LOADED_SCRIPTS_SUPPORTED }], VIEW_CONTAINER);
|
||||
|
||||
registerCommands();
|
||||
|
||||
// register action to open viewlet
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionRegistryExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDebugPanelAction, OpenDebugPanelAction.ID, OpenDebugPanelAction.LABEL, openPanelKb), 'View: Debug Console', nls.localize('view', "View"));
|
||||
@@ -132,15 +131,6 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
|
||||
const debugCategory = nls.localize('debugCategory', "Debug");
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(StartAction, StartAction.ID, StartAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE.toNegated()), 'Debug: Start Debugging', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(StepOverAction, StepOverAction.ID, StepOverAction.LABEL, { primary: KeyCode.F10 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Step Over', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(StepIntoAction, StepIntoAction.ID, StepIntoAction.LABEL, { primary: KeyCode.F11 }, CONTEXT_IN_DEBUG_MODE, KeybindingWeight.WorkbenchContrib + 1), 'Debug: Step Into', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(StepOutAction, StepOutAction.ID, StepOutAction.LABEL, { primary: KeyMod.Shift | KeyCode.F11 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Step Out', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(RestartAction, RestartAction.ID, RestartAction.LABEL, { primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Restart', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(StopAction, StopAction.ID, StopAction.LABEL, { primary: KeyMod.Shift | KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Stop', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(DisconnectAction, DisconnectAction.ID, DisconnectAction.LABEL), 'Debug: Disconnect', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ContinueAction, ContinueAction.ID, ContinueAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Continue', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(PauseAction, PauseAction.ID, PauseAction.LABEL, { primary: KeyCode.F6 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Pause', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(TerminateThreadAction, TerminateThreadAction.ID, TerminateThreadAction.LABEL, undefined, CONTEXT_IN_DEBUG_MODE), 'Debug: Terminate Thread', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL), 'Debug: Open launch.json', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(AddFunctionBreakpointAction, AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL), 'Debug: Add Function Breakpoint', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ReapplyBreakpointsAction, ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory);
|
||||
@@ -148,10 +138,38 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(RunAction, RunAction.I
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(RemoveAllBreakpointsAction, RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL), 'Debug: Remove All Breakpoints', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EnableAllBreakpointsAction, EnableAllBreakpointsAction.ID, EnableAllBreakpointsAction.LABEL), 'Debug: Enable All Breakpoints', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(DisableAllBreakpointsAction, DisableAllBreakpointsAction.ID, DisableAllBreakpointsAction.LABEL), 'Debug: Disable All Breakpoints', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusReplAction, FocusReplAction.ID, FocusReplAction.LABEL), 'Debug: Focus on Debug Console View', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SelectAndStartAction, SelectAndStartAction.ID, SelectAndStartAction.LABEL), 'Debug: Select and Start Debugging', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ClearReplAction, ClearReplAction.ID, ClearReplAction.LABEL), 'Debug: Clear Console', debugCategory);
|
||||
|
||||
const registerDebugCommandPaletteItem = (id: string, title: string, when?: ContextKeyExpr, precondition?: ContextKeyExpr) => {
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
when,
|
||||
command: {
|
||||
id,
|
||||
title: `Debug: ${title}`,
|
||||
precondition
|
||||
}
|
||||
});
|
||||
};
|
||||
const restartLabel = nls.localize('restartDebug', "Restart");
|
||||
const stepOverLabel = nls.localize('stepOverDebug', "Step Over");
|
||||
const stepIntoLabel = nls.localize('stepIntoDebug', "Step Into");
|
||||
const stepOutLabel = nls.localize('stepOutDebug', "Step Out");
|
||||
const pauseLabel = nls.localize('pauseDebug', "Pause");
|
||||
const disconnectLabel = nls.localize('disconnect', "Disconnect");
|
||||
const stopLabel = nls.localize('stop', "Stop");
|
||||
const continueLabel = nls.localize('continueDebug', "Continue");
|
||||
registerDebugCommandPaletteItem(RESTART_SESSION_ID, restartLabel);
|
||||
registerDebugCommandPaletteItem(TERMINATE_THREAD_ID, nls.localize('terminateThread', "Terminate Thread"), CONTEXT_IN_DEBUG_MODE);
|
||||
registerDebugCommandPaletteItem(STEP_OVER_ID, stepOverLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugCommandPaletteItem(STEP_INTO_ID, stepIntoLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugCommandPaletteItem(STEP_OUT_ID, stepOutLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugCommandPaletteItem(PAUSE_ID, pauseLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('running'));
|
||||
registerDebugCommandPaletteItem(DISCONNECT_ID, disconnectLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_FOCUSED_SESSION_IS_ATTACH);
|
||||
registerDebugCommandPaletteItem(STOP_ID, stopLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated());
|
||||
registerDebugCommandPaletteItem(CONTINUE_ID, continueLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugCommandPaletteItem(FOCUS_REPL_ID, nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusConsole' }, 'Focus on Debug Console View'));
|
||||
|
||||
// Register Quick Open
|
||||
(Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler(
|
||||
new QuickOpenHandlerDescriptor(
|
||||
@@ -235,8 +253,6 @@ configurationRegistry.registerConfiguration({
|
||||
}
|
||||
});
|
||||
|
||||
registerCommands();
|
||||
|
||||
// Register Debug Status
|
||||
const statusBar = Registry.as<IStatusbarRegistry>(StatusExtensions.Statusbar);
|
||||
statusBar.registerStatusbarItem(new StatusbarItemDescriptor(DebugStatus, StatusbarAlignment.LEFT, 30 /* Low Priority */));
|
||||
@@ -260,16 +276,40 @@ const registerDebugToolbarItem = (id: string, title: string, icon: string, order
|
||||
});
|
||||
};
|
||||
|
||||
registerDebugToolbarItem(ContinueAction.ID, ContinueAction.LABEL, 'continue', 10, CONTEXT_DEBUG_STATE.notEqualsTo('running'));
|
||||
registerDebugToolbarItem(PauseAction.ID, PauseAction.LABEL, 'pause', 10, CONTEXT_DEBUG_STATE.isEqualTo('running'));
|
||||
registerDebugToolbarItem(StopAction.ID, StopAction.LABEL, 'stop', 70, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated());
|
||||
registerDebugToolbarItem(DisconnectAction.ID, DisconnectAction.LABEL, 'disconnect', 70, CONTEXT_FOCUSED_SESSION_IS_ATTACH);
|
||||
registerDebugToolbarItem(StepOverAction.ID, StepOverAction.LABEL, 'step-over', 20, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(StepIntoAction.ID, StepIntoAction.LABEL, 'step-into', 30, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(StepOutAction.ID, StepOutAction.LABEL, 'step-out', 40, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(RestartAction.ID, RestartAction.LABEL, 'restart', 60);
|
||||
registerDebugToolbarItem(StepBackAction.ID, StepBackAction.LABEL, 'step-back', 50, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(ReverseContinueAction.ID, ReverseContinueAction.LABEL, 'reverse-continue', 60, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(CONTINUE_ID, continueLabel, 'continue', 10, CONTEXT_DEBUG_STATE.notEqualsTo('running'));
|
||||
registerDebugToolbarItem(PAUSE_ID, pauseLabel, 'pause', 10, CONTEXT_DEBUG_STATE.isEqualTo('running'));
|
||||
registerDebugToolbarItem(STOP_ID, stopLabel, 'stop', 70, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated());
|
||||
registerDebugToolbarItem(DISCONNECT_ID, disconnectLabel, 'disconnect', 70, CONTEXT_FOCUSED_SESSION_IS_ATTACH);
|
||||
registerDebugToolbarItem(STEP_OVER_ID, stepOverLabel, 'step-over', 20, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(STEP_INTO_ID, stepIntoLabel, 'step-into', 30, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(STEP_OUT_ID, stepOutLabel, 'step-out', 40, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(RESTART_SESSION_ID, restartLabel, 'restart', 60);
|
||||
registerDebugToolbarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 'step-back', 50, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugToolbarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 'reverse-continue', 60, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
|
||||
// Debug callstack context menu
|
||||
const registerDebugCallstackItem = (id: string, title: string, order: number, when?: ContextKeyExpr, precondition?: ContextKeyExpr, group = 'navigation') => {
|
||||
MenuRegistry.appendMenuItem(MenuId.DebugCallStackContext, {
|
||||
group,
|
||||
when,
|
||||
order,
|
||||
command: {
|
||||
id,
|
||||
title,
|
||||
precondition
|
||||
}
|
||||
});
|
||||
};
|
||||
registerDebugCallstackItem(RESTART_SESSION_ID, restartLabel, 10, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'));
|
||||
registerDebugCallstackItem(STOP_ID, stopLabel, 20, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'));
|
||||
registerDebugCallstackItem(PAUSE_ID, pauseLabel, 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('running')));
|
||||
registerDebugCallstackItem(CONTINUE_ID, continueLabel, 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped')));
|
||||
registerDebugCallstackItem(STEP_OVER_ID, stepOverLabel, 20, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugCallstackItem(STEP_INTO_ID, stepIntoLabel, 30, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugCallstackItem(STEP_OUT_ID, stepOutLabel, 40, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
|
||||
registerDebugCallstackItem(TERMINATE_THREAD_ID, nls.localize('terminateThread', "Terminate Thread"), 10, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), undefined, 'termination');
|
||||
registerDebugCallstackItem(RESTART_FRAME_ID, nls.localize('restartFrame', "Restart Frame"), 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('stackFrame'), CONTEXT_RESTART_FRAME_SUPPORTED));
|
||||
registerDebugCallstackItem(COPY_STACK_TRACE_ID, nls.localize('copyStackTrace', "Copy Call Stack"), 20, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('stackFrame'));
|
||||
|
||||
// View menu
|
||||
|
||||
@@ -318,7 +358,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
group: '1_debug',
|
||||
command: {
|
||||
id: StopAction.ID,
|
||||
id: STOP_ID,
|
||||
title: nls.localize({ key: 'miStopDebugging', comment: ['&& denotes a mnemonic'] }, "&&Stop Debugging"),
|
||||
precondition: CONTEXT_IN_DEBUG_MODE
|
||||
},
|
||||
@@ -328,7 +368,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
group: '1_debug',
|
||||
command: {
|
||||
id: RestartAction.ID,
|
||||
id: RESTART_SESSION_ID,
|
||||
title: nls.localize({ key: 'miRestart Debugging', comment: ['&& denotes a mnemonic'] }, "&&Restart Debugging"),
|
||||
precondition: CONTEXT_IN_DEBUG_MODE
|
||||
},
|
||||
@@ -358,7 +398,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
group: '3_step',
|
||||
command: {
|
||||
id: StepOverAction.ID,
|
||||
id: STEP_OVER_ID,
|
||||
title: nls.localize({ key: 'miStepOver', comment: ['&& denotes a mnemonic'] }, "Step &&Over"),
|
||||
precondition: CONTEXT_DEBUG_STATE.isEqualTo('stopped')
|
||||
},
|
||||
@@ -368,7 +408,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
group: '3_step',
|
||||
command: {
|
||||
id: StepIntoAction.ID,
|
||||
id: STEP_INTO_ID,
|
||||
title: nls.localize({ key: 'miStepInto', comment: ['&& denotes a mnemonic'] }, "Step &&Into"),
|
||||
precondition: CONTEXT_DEBUG_STATE.isEqualTo('stopped')
|
||||
},
|
||||
@@ -378,7 +418,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
group: '3_step',
|
||||
command: {
|
||||
id: StepOutAction.ID,
|
||||
id: STEP_OUT_ID,
|
||||
title: nls.localize({ key: 'miStepOut', comment: ['&& denotes a mnemonic'] }, "Step O&&ut"),
|
||||
precondition: CONTEXT_DEBUG_STATE.isEqualTo('stopped')
|
||||
},
|
||||
@@ -388,7 +428,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
|
||||
group: '3_step',
|
||||
command: {
|
||||
id: ContinueAction.ID,
|
||||
id: CONTINUE_ID,
|
||||
title: nls.localize({ key: 'miContinue', comment: ['&& denotes a mnemonic'] }, "&&Continue"),
|
||||
precondition: CONTEXT_DEBUG_STATE.isEqualTo('stopped')
|
||||
},
|
||||
@@ -502,11 +542,11 @@ if (isMacintosh) {
|
||||
|
||||
registerTouchBarEntry(StartAction.ID, StartAction.LABEL, 0, CONTEXT_IN_DEBUG_MODE.toNegated(), 'continue-tb.png');
|
||||
registerTouchBarEntry(RunAction.ID, RunAction.LABEL, 1, CONTEXT_IN_DEBUG_MODE.toNegated(), 'continue-without-debugging-tb.png');
|
||||
registerTouchBarEntry(ContinueAction.ID, ContinueAction.LABEL, 0, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'continue-tb.png');
|
||||
registerTouchBarEntry(PauseAction.ID, PauseAction.LABEL, 1, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.notEquals('debugState', 'stopped')), 'pause-tb.png');
|
||||
registerTouchBarEntry(StepOverAction.ID, StepOverAction.LABEL, 2, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepover-tb.png');
|
||||
registerTouchBarEntry(StepIntoAction.ID, StepIntoAction.LABEL, 3, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepinto-tb.png');
|
||||
registerTouchBarEntry(StepOutAction.ID, StepOutAction.LABEL, 4, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepout-tb.png');
|
||||
registerTouchBarEntry(RestartAction.ID, RestartAction.LABEL, 5, CONTEXT_IN_DEBUG_MODE, 'restart-tb.png');
|
||||
registerTouchBarEntry(StopAction.ID, StopAction.LABEL, 6, CONTEXT_IN_DEBUG_MODE, 'stop-tb.png');
|
||||
registerTouchBarEntry(CONTINUE_ID, continueLabel, 0, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'continue-tb.png');
|
||||
registerTouchBarEntry(PAUSE_ID, pauseLabel, 1, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.notEquals('debugState', 'stopped')), 'pause-tb.png');
|
||||
registerTouchBarEntry(STEP_OVER_ID, stepOverLabel, 2, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepover-tb.png');
|
||||
registerTouchBarEntry(STEP_INTO_ID, stepIntoLabel, 3, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepinto-tb.png');
|
||||
registerTouchBarEntry(STEP_OUT_ID, stepOutLabel, 4, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepout-tb.png');
|
||||
registerTouchBarEntry(RESTART_SESSION_ID, restartLabel, 5, CONTEXT_IN_DEBUG_MODE, 'restart-tb.png');
|
||||
registerTouchBarEntry(STOP_ID, stopLabel, 6, CONTEXT_IN_DEBUG_MODE, 'stop-tb.png');
|
||||
}
|
||||
|
||||
@@ -12,170 +12,11 @@ import * as path from 'vs/base/common/path';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IOutputService } from 'vs/workbench/contrib/output/common/output';
|
||||
import { IDebugAdapter, IDebugAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IDebugAdapterServer } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IDebugAdapterServer } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
/**
|
||||
* Abstract implementation of the low level API for a debug adapter.
|
||||
* Missing is how this API communicates with the debug adapter.
|
||||
*/
|
||||
export abstract class AbstractDebugAdapter implements IDebugAdapter {
|
||||
|
||||
private sequence: number;
|
||||
private pendingRequests: Map<number, (e: DebugProtocol.Response) => void>;
|
||||
private requestCallback: (request: DebugProtocol.Request) => void;
|
||||
private eventCallback: (request: DebugProtocol.Event) => void;
|
||||
private messageCallback: (message: DebugProtocol.ProtocolMessage) => void;
|
||||
|
||||
protected readonly _onError: Emitter<Error>;
|
||||
protected readonly _onExit: Emitter<number | null>;
|
||||
|
||||
constructor() {
|
||||
this.sequence = 1;
|
||||
this.pendingRequests = new Map();
|
||||
|
||||
this._onError = new Emitter<Error>();
|
||||
this._onExit = new Emitter<number>();
|
||||
}
|
||||
|
||||
abstract startSession(): Promise<void>;
|
||||
abstract stopSession(): Promise<void>;
|
||||
|
||||
abstract sendMessage(message: DebugProtocol.ProtocolMessage): void;
|
||||
|
||||
get onError(): Event<Error> {
|
||||
return this._onError.event;
|
||||
}
|
||||
|
||||
get onExit(): Event<number | null> {
|
||||
return this._onExit.event;
|
||||
}
|
||||
|
||||
onMessage(callback: (message: DebugProtocol.ProtocolMessage) => void): void {
|
||||
if (this.eventCallback) {
|
||||
this._onError.fire(new Error(`attempt to set more than one 'Message' callback`));
|
||||
}
|
||||
this.messageCallback = callback;
|
||||
}
|
||||
|
||||
onEvent(callback: (event: DebugProtocol.Event) => void): void {
|
||||
if (this.eventCallback) {
|
||||
this._onError.fire(new Error(`attempt to set more than one 'Event' callback`));
|
||||
}
|
||||
this.eventCallback = callback;
|
||||
}
|
||||
|
||||
onRequest(callback: (request: DebugProtocol.Request) => void): void {
|
||||
if (this.requestCallback) {
|
||||
this._onError.fire(new Error(`attempt to set more than one 'Request' callback`));
|
||||
}
|
||||
this.requestCallback = callback;
|
||||
}
|
||||
|
||||
sendResponse(response: DebugProtocol.Response): void {
|
||||
if (response.seq > 0) {
|
||||
this._onError.fire(new Error(`attempt to send more than one response for command ${response.command}`));
|
||||
} else {
|
||||
this.internalSend('response', response);
|
||||
}
|
||||
}
|
||||
|
||||
sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void {
|
||||
|
||||
const request: any = {
|
||||
command: command
|
||||
};
|
||||
if (args && Object.keys(args).length > 0) {
|
||||
request.arguments = args;
|
||||
}
|
||||
|
||||
this.internalSend('request', request);
|
||||
|
||||
if (typeof timeout === 'number') {
|
||||
const timer = setTimeout(() => {
|
||||
clearTimeout(timer);
|
||||
const clb = this.pendingRequests.get(request.seq);
|
||||
if (clb) {
|
||||
this.pendingRequests.delete(request.seq);
|
||||
const err: DebugProtocol.Response = {
|
||||
type: 'response',
|
||||
seq: 0,
|
||||
request_seq: request.seq,
|
||||
success: false,
|
||||
command,
|
||||
message: `timeout after ${timeout} ms`
|
||||
};
|
||||
clb(err);
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
if (clb) {
|
||||
// store callback for this request
|
||||
this.pendingRequests.set(request.seq, clb);
|
||||
}
|
||||
}
|
||||
|
||||
acceptMessage(message: DebugProtocol.ProtocolMessage): void {
|
||||
if (this.messageCallback) {
|
||||
this.messageCallback(message);
|
||||
} else {
|
||||
switch (message.type) {
|
||||
case 'event':
|
||||
if (this.eventCallback) {
|
||||
this.eventCallback(<DebugProtocol.Event>message);
|
||||
}
|
||||
break;
|
||||
case 'request':
|
||||
if (this.requestCallback) {
|
||||
this.requestCallback(<DebugProtocol.Request>message);
|
||||
}
|
||||
break;
|
||||
case 'response':
|
||||
const response = <DebugProtocol.Response>message;
|
||||
const clb = this.pendingRequests.get(response.request_seq);
|
||||
if (clb) {
|
||||
this.pendingRequests.delete(response.request_seq);
|
||||
clb(response);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private internalSend(typ: 'request' | 'response' | 'event', message: DebugProtocol.ProtocolMessage): void {
|
||||
|
||||
message.type = typ;
|
||||
message.seq = this.sequence++;
|
||||
|
||||
this.sendMessage(message);
|
||||
}
|
||||
|
||||
protected cancelPending() {
|
||||
const pending = this.pendingRequests;
|
||||
this.pendingRequests = new Map();
|
||||
setTimeout(_ => {
|
||||
pending.forEach((callback, request_seq) => {
|
||||
const err: DebugProtocol.Response = {
|
||||
type: 'response',
|
||||
seq: 0,
|
||||
request_seq,
|
||||
success: false,
|
||||
command: 'canceled',
|
||||
message: 'canceled'
|
||||
};
|
||||
callback(err);
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.cancelPending();
|
||||
}
|
||||
}
|
||||
import { AbstractDebugAdapter } from '../common/abstractDebugAdapter';
|
||||
|
||||
/**
|
||||
* An implementation that communicates via two streams with the debug adapter.
|
||||
|
||||
Reference in New Issue
Block a user