Skip to content

Commit

Permalink
step into targets support
Browse files Browse the repository at this point in the history
fixes #90793
  • Loading branch information
isidorn committed May 14, 2020
1 parent ae4a8e3 commit 054c342
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 6 deletions.
48 changes: 47 additions & 1 deletion src/vs/workbench/contrib/debug/browser/debugEditorActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ import { Range } from 'vs/editor/common/core/range';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ServicesAccessor, registerEditorAction, EditorAction, IActionOptions } from 'vs/editor/browser/editorExtensions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE, State, VIEWLET_ID, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, REPL_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE, State, VIEWLET_ID, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, REPL_VIEW_ID, CONTEXT_STEP_INTO_TARGETS_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { openBreakpointSource } from 'vs/workbench/contrib/debug/browser/breakpointsView';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { PanelFocusContext } from 'vs/workbench/common/panel';
import { IViewsService } from 'vs/workbench/common/views';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { Action } from 'vs/base/common/actions';
import { getDomNodePagePosition } from 'vs/base/browser/dom';

export const TOGGLE_BREAKPOINT_ID = 'editor.debug.action.toggleBreakpoint';
class ToggleBreakpointAction extends EditorAction {
Expand Down Expand Up @@ -241,6 +244,48 @@ class ShowDebugHoverAction extends EditorAction {
}
}

class StepIntoTargetsAction extends EditorAction {

public static readonly ID = 'editor.debug.action.stepIntoTargets';
public static readonly LABEL = nls.localize('stepIntoTargets', "Step Into Targets...");

constructor() {
super({
id: StepIntoTargetsAction.ID,
label: StepIntoTargetsAction.LABEL,
alias: 'Debug: Step Into Targets...',
precondition: ContextKeyExpr.and(CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), EditorContextKeys.editorTextFocus),
contextMenuOpts: {
group: 'debug',
order: 1.5
}
});
}

async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
const debugService = accessor.get(IDebugService);
const contextMenuService = accessor.get(IContextMenuService);
const session = debugService.getViewModel().focusedSession;
const frame = debugService.getViewModel().focusedStackFrame;

if (session && frame && editor.hasModel()) {
const targets = await session.stepInTargets(frame.frameId);
const position = editor.getPosition();
const cursorCoords = editor.getScrolledVisiblePosition(position);
const editorCoords = getDomNodePagePosition(editor.getDomNode());
const x = editorCoords.left + cursorCoords.left;
const y = editorCoords.top + cursorCoords.top + cursorCoords.height;

contextMenuService.showContextMenu({
getAnchor: () => ({ x, y }),
getActions: () => {
return targets.map(t => new Action(`stepIntoTarget:${t.id}`, t.label, undefined, true, () => session.stepIn(frame.thread.threadId, t.id)));
}
});
}
}
}

class GoToBreakpointAction extends EditorAction {
constructor(private isNext: boolean, opts: IActionOptions) {
super(opts);
Expand Down Expand Up @@ -307,6 +352,7 @@ registerEditorAction(ToggleBreakpointAction);
registerEditorAction(ConditionalBreakpointAction);
registerEditorAction(LogPointAction);
registerEditorAction(RunToCursorAction);
registerEditorAction(StepIntoTargetsAction);
registerEditorAction(SelectionToReplAction);
registerEditorAction(SelectionToWatchExpressionsAction);
registerEditorAction(ShowDebugHoverAction);
Expand Down
13 changes: 11 additions & 2 deletions src/vs/workbench/contrib/debug/browser/debugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,12 +489,12 @@ export class DebugSession implements IDebugSession {
await this.raw.next({ threadId });
}

async stepIn(threadId: number): Promise<void> {
async stepIn(threadId: number, targetId?: number): Promise<void> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepIn'));
}

await this.raw.stepIn({ threadId });
await this.raw.stepIn({ threadId, targetId });
}

async stepOut(threadId: number): Promise<void> {
Expand Down Expand Up @@ -613,6 +613,15 @@ export class DebugSession implements IDebugSession {
}, token);
}

async stepInTargets(frameId: number): Promise<{ id: number, label: string }[]> {
if (!this.raw) {
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepInTargets')));
}

const response = await this.raw.stepInTargets({ frameId });
return response.body.targets;
}

async cancel(progressId: string): Promise<DebugProtocol.CancelResponse> {
if (!this.raw) {
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'cancel')));
Expand Down
7 changes: 7 additions & 0 deletions src/vs/workbench/contrib/debug/browser/rawDebugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,13 @@ export class RawDebugSession implements IDisposable {
return Promise.reject(new Error('restartFrame not supported'));
}

stepInTargets(args: DebugProtocol.StepInTargetsArguments): Promise<DebugProtocol.StepInTargetsResponse> {
if (this.capabilities.supportsStepInTargetsRequest) {
return this.send('stepInTargets', args);
}
return Promise.reject(new Error('stepInTargets not supported'));
}

completions(args: DebugProtocol.CompletionsArguments, token: CancellationToken): Promise<DebugProtocol.CompletionsResponse> {
if (this.capabilities.supportsCompletionsRequest) {
return this.send<DebugProtocol.CompletionsResponse>('completions', args, token);
Expand Down
4 changes: 3 additions & 1 deletion src/vs/workbench/contrib/debug/common/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const CONTEXT_FOCUSED_SESSION_IS_ATTACH = new RawContextKey<boolean>('foc
export const CONTEXT_STEP_BACK_SUPPORTED = new RawContextKey<boolean>('stepBackSupported', false);
export const CONTEXT_RESTART_FRAME_SUPPORTED = new RawContextKey<boolean>('restartFrameSupported', false);
export const CONTEXT_JUMP_TO_CURSOR_SUPPORTED = new RawContextKey<boolean>('jumpToCursorSupported', false);
export const CONTEXT_STEP_INTO_TARGETS_SUPPORTED = new RawContextKey<boolean>('stepIntoTargetsSupported', false);
export const CONTEXT_BREAKPOINTS_EXIST = new RawContextKey<boolean>('breakpointsExist', false);

export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
Expand Down Expand Up @@ -229,14 +230,15 @@ export interface IDebugSession extends ITreeElement {

restartFrame(frameId: number, threadId: number): Promise<void>;
next(threadId: number): Promise<void>;
stepIn(threadId: number): Promise<void>;
stepIn(threadId: number, targetId?: number): Promise<void>;
stepOut(threadId: number): Promise<void>;
stepBack(threadId: number): Promise<void>;
continue(threadId: number): Promise<void>;
reverseContinue(threadId: number): Promise<void>;
pause(threadId: number): Promise<void>;
terminateThreads(threadIds: number[]): Promise<void>;

stepInTargets(frameId: number): Promise<{ id: number, label: string }[]>;
completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise<DebugProtocol.CompletionsResponse>;
setVariable(variablesReference: number | undefined, name: string, value: string): Promise<DebugProtocol.SetVariableResponse>;
loadSource(resource: uri): Promise<DebugProtocol.SourceResponse>;
Expand Down
5 changes: 4 additions & 1 deletion src/vs/workbench/contrib/debug/common/debugViewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED } 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, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils';

Expand All @@ -27,6 +27,7 @@ export class ViewModel implements IViewModel {
private stepBackSupportedContextKey: IContextKey<boolean>;
private focusedSessionIsAttach: IContextKey<boolean>;
private restartFrameSupportedContextKey: IContextKey<boolean>;
private stepIntoTargetsSupported: IContextKey<boolean>;
private jumpToCursorSupported: IContextKey<boolean>;

constructor(contextKeyService: IContextKeyService) {
Expand All @@ -37,6 +38,7 @@ export class ViewModel implements IViewModel {
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);
this.stepIntoTargetsSupported = CONTEXT_STEP_INTO_TARGETS_SUPPORTED.bindTo(contextKeyService);
this.jumpToCursorSupported = CONTEXT_JUMP_TO_CURSOR_SUPPORTED.bindTo(contextKeyService);
}

Expand Down Expand Up @@ -67,6 +69,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);
this.stepIntoTargetsSupported.set(session ? !!session.capabilities.supportsStepInTargetsRequest : false);
this.jumpToCursorSupported.set(session ? !!session.capabilities.supportsGotoTargetsRequest : false);
const attach = !!session && isSessionAttach(session);
this.focusedSessionIsAttach.set(attach);
Expand Down
6 changes: 5 additions & 1 deletion src/vs/workbench/contrib/debug/test/common/mockDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ export class MockDebugService implements IDebugService {

export class MockSession implements IDebugSession {

stepInTargets(frameId: number): Promise<{ id: number; label: string; }[]> {
throw new Error('Method not implemented.');
}

cancel(_progressId: string): Promise<DebugProtocol.CancelResponse> {
throw new Error('Method not implemented.');
}
Expand Down Expand Up @@ -304,7 +308,7 @@ export class MockSession implements IDebugSession {
next(threadId: number): Promise<void> {
throw new Error('Method not implemented.');
}
stepIn(threadId: number): Promise<void> {
stepIn(threadId: number, targetId?: number): Promise<void> {
throw new Error('Method not implemented.');
}
stepOut(threadId: number): Promise<void> {
Expand Down

0 comments on commit 054c342

Please sign in to comment.