From e0c9b7b3afeb5b8cdf2d2e386c9fced0644d36fb Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 13 Jun 2019 11:15:00 +0200 Subject: [PATCH] debug: add jump to cursor --- .../contrib/debug/browser/debugCommands.ts | 62 ++++++++++++++++--- .../debug/browser/debugEditorActions.ts | 12 +--- .../electron-browser/debug.contribution.ts | 10 ++- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 4426616cf45..13b6bba1b9f 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -9,7 +9,7 @@ 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, IStackFrame, IThread, IDebugSession, CONTEXT_DEBUG_STATE, REPL_ID, IDebugConfiguration } from 'vs/workbench/contrib/debug/common/debug'; +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, IDebugConfiguration, CONTEXT_JUMP_TO_CURSOR_SUPPORTED } 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'; @@ -31,6 +31,7 @@ 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'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; export const ADD_CONFIGURATION_ID = 'debug.addConfiguration'; export const TOGGLE_INLINE_BREAKPOINT_ID = 'editor.debug.action.toggleInlineBreakpoint'; @@ -48,6 +49,7 @@ 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'; +export const JUMP_TO_CURSOR_ID = 'debug.jumpToCursor'; function getThreadAndRun(accessor: ServicesAccessor, thread: IThread | undefined, run: (thread: IThread) => Promise, ): void { const debugService = accessor.get(IDebugService); @@ -98,6 +100,57 @@ export function registerCommands(): void { } }); + CommandsRegistry.registerCommand({ + id: JUMP_TO_CURSOR_ID, + handler: async (accessor: ServicesAccessor) => { + const debugService = accessor.get(IDebugService); + const stackFrame = debugService.getViewModel().focusedStackFrame; + const editorService = accessor.get(IEditorService); + const activeEditor = editorService.activeEditor; + const notificationService = accessor.get(INotificationService); + const quickInputService = accessor.get(IQuickInputService); + + if (stackFrame && isCodeEditor(activeEditor)) { + const position = activeEditor.getPosition(); + const resource = activeEditor.getResource(); + if (position && resource) { + const source = stackFrame.thread.session.getSourceForUri(resource); + if (source) { + const response = await stackFrame.thread.session.gotoTargets(source, position.lineNumber, position.column); + const targets = response.body.targets; + if (targets.length) { + let id = targets[0].id; + if (targets.length > 1) { + const picks = targets.map(t => ({ label: t.label, _id: t.id })); + const pick = await quickInputService.pick(picks, { placeHolder: nls.localize('chooseLocation', "Choose the specific location") }); + if (!pick) { + return; + } + + id = pick._id; + } + + return await stackFrame.thread.session.goto(stackFrame.thread.threadId, id); + } + } + } + } + + return notificationService.warn(nls.localize('noExecutableCode', "No executable code is associated at the current cursor position.")); + } + }); + + MenuRegistry.appendMenuItem(MenuId.EditorContext, { + command: { + id: JUMP_TO_CURSOR_ID, + title: nls.localize('jumpToCursor', "Jump to Cursor"), + category: { value: nls.localize('debug', "Debug"), original: 'Debug' } + }, + when: ContextKeyExpr.and(CONTEXT_JUMP_TO_CURSOR_SUPPORTED, EditorContextKeys.editorTextFocus), + group: 'debug', + order: 3 + }); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: RESTART_SESSION_ID, weight: KeybindingWeight.WorkbenchContrib, @@ -432,13 +485,6 @@ export function registerCommands(): void { handler: inlineBreakpointHandler }); - MenuRegistry.appendMenuItem(MenuId.CommandPalette, { - command: { - id: TOGGLE_INLINE_BREAKPOINT_ID, - title: { value: nls.localize('inlineBreakpoint', "Inline Breakpoint"), original: 'Inline Breakpoint' }, - category: { value: nls.localize('debug', "Debug"), original: 'Debug' } - } - }); MenuRegistry.appendMenuItem(MenuId.EditorContext, { command: { id: TOGGLE_INLINE_BREAKPOINT_ID, diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts index a55cb493a1e..060f9197074 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts @@ -17,7 +17,6 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic 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 { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; export const TOGGLE_BREAKPOINT_ID = 'editor.debug.action.toggleBreakpoint'; class ToggleBreakpointAction extends EditorAction { @@ -99,7 +98,7 @@ class LogPointAction extends EditorAction { } } -class RunToCursorAction extends EditorAction { +export class RunToCursorAction extends EditorAction { public static ID = 'editor.debug.action.runToCursor'; public static LABEL = nls.localize('runToCursor', "Run to Cursor"); @@ -313,12 +312,3 @@ registerEditorAction(SelectionToWatchExpressionsAction); registerEditorAction(ShowDebugHoverAction); registerEditorAction(GoToNextBreakpointAction); registerEditorAction(GoToPreviousBreakpointAction); -MenuRegistry.appendMenuItem(MenuId.CommandPalette, { - command: { - id: RunToCursorAction.ID, - title: { value: RunToCursorAction.LABEL, original: 'Debug: Run to Cursor' }, - category: nls.localize('debug', "Debug") - }, - group: 'debug', - when: ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped')), -}); diff --git a/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts index 35254ac79dc..eee7b27c4af 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts @@ -20,7 +20,7 @@ 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_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_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, CONTEXT_JUMP_TO_CURSOR_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'; @@ -29,7 +29,7 @@ import { StartAction, AddFunctionBreakpointAction, ConfigureAction, DisableAllBr 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, 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 { 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, JUMP_TO_CURSOR_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'; @@ -43,7 +43,7 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { LoadedScriptsView } from 'vs/workbench/contrib/debug/browser/loadedScriptsView'; -import { TOGGLE_LOG_POINT_ID, TOGGLE_CONDITIONAL_BREAKPOINT_ID, TOGGLE_BREAKPOINT_ID } from 'vs/workbench/contrib/debug/browser/debugEditorActions'; +import { TOGGLE_LOG_POINT_ID, TOGGLE_CONDITIONAL_BREAKPOINT_ID, TOGGLE_BREAKPOINT_ID, RunToCursorAction } from 'vs/workbench/contrib/debug/browser/debugEditorActions'; import { WatchExpressionsView } from 'vs/workbench/contrib/debug/browser/watchExpressionsView'; import { VariablesView } from 'vs/workbench/contrib/debug/browser/variablesView'; import { ClearReplAction, Repl } from 'vs/workbench/contrib/debug/browser/repl'; @@ -165,6 +165,10 @@ registerDebugCommandPaletteItem(DISCONNECT_ID, disconnectLabel, CONTEXT_IN_DEBUG 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')); +registerDebugCommandPaletteItem(JUMP_TO_CURSOR_ID, nls.localize('jumpToCursor', "Jump to Cursor"), ContextKeyExpr.and(CONTEXT_JUMP_TO_CURSOR_SUPPORTED)); +registerDebugCommandPaletteItem(RunToCursorAction.ID, RunToCursorAction.LABEL, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'))); +registerDebugCommandPaletteItem(TOGGLE_INLINE_BREAKPOINT_ID, nls.localize('inlineBreakpoint', "Inline Breakpoint")); + // Register Quick Open (Registry.as(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler(