debugEditorActions.ts 11.0 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { Range } from 'vs/editor/common/core/range';
10
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
11
import { ServicesAccessor, registerEditorAction, EditorAction, IActionOptions } from 'vs/editor/browser/editorExtensions';
12
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
13
import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE, State, REPL_ID, VIEWLET_ID, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint } from 'vs/workbench/parts/debug/common/debug';
14
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
B
Benjamin Pasero 已提交
15
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
16
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
B
Benjamin Pasero 已提交
17
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
K
Krzysztof Cieslak 已提交
18
import { openBreakpointSource } from 'vs/workbench/parts/debug/browser/breakpointsView';
19
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
I
isidor 已提交
20
import { PanelFocusContext } from 'vs/workbench/browser/parts/panel/panelPart';
21

22
export const TOGGLE_BREAKPOINT_ID = 'editor.debug.action.toggleBreakpoint';
23 24 25
class ToggleBreakpointAction extends EditorAction {
	constructor() {
		super({
26
			id: TOGGLE_BREAKPOINT_ID,
27 28 29 30
			label: nls.localize('toggleBreakpointAction', "Debug: Toggle Breakpoint"),
			alias: 'Debug: Toggle Breakpoint',
			precondition: null,
			kbOpts: {
31
				kbExpr: EditorContextKeys.editorTextFocus,
A
Alex Dima 已提交
32
				primary: KeyCode.F9,
33
				weight: KeybindingWeight.EditorContrib
34 35 36 37
			}
		});
	}

38
	public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<any> {
39 40 41 42
		const debugService = accessor.get(IDebugService);

		const position = editor.getPosition();
		const modelUri = editor.getModel().uri;
I
isidor 已提交
43
		const bps = debugService.getModel().getBreakpoints({ lineNumber: position.lineNumber, uri: modelUri });
44 45

		if (bps.length) {
I
isidor 已提交
46
			return Promise.all(bps.map(bp => debugService.removeBreakpoints(bp.getId())));
47 48
		}
		if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) {
K
Format  
Kenneth Auchenberg 已提交
49
			return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber }], 'debugEditorActions.toggleBreakpointAction');
50 51
		}

I
isidor 已提交
52
		return Promise.resolve(null);
53 54 55
	}
}

56
export const TOGGLE_CONDITIONAL_BREAKPOINT_ID = 'editor.debug.action.conditionalBreakpoint';
57
class ConditionalBreakpointAction extends EditorAction {
58 59 60

	constructor() {
		super({
61
			id: TOGGLE_CONDITIONAL_BREAKPOINT_ID,
62 63 64 65 66 67
			label: nls.localize('conditionalBreakpointEditorAction', "Debug: Add Conditional Breakpoint..."),
			alias: 'Debug: Add Conditional Breakpoint...',
			precondition: null
		});
	}

68
	public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
69 70
		const debugService = accessor.get(IDebugService);

71
		const { lineNumber, column } = editor.getPosition();
72
		if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) {
73
			editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(lineNumber, column);
74 75 76 77
		}
	}
}

78
export const TOGGLE_LOG_POINT_ID = 'editor.debug.action.toggleLogPoint';
79 80 81 82
class LogPointAction extends EditorAction {

	constructor() {
		super({
83
			id: TOGGLE_LOG_POINT_ID,
I
isidor 已提交
84 85
			label: nls.localize('logPointEditorAction', "Debug: Add Logpoint..."),
			alias: 'Debug: Add Logpoint...',
86 87 88 89 90 91 92 93 94 95 96 97 98 99
			precondition: null
		});
	}

	public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
		const debugService = accessor.get(IDebugService);

		const { lineNumber, column } = editor.getPosition();
		if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) {
			editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(lineNumber, column, BreakpointWidgetContext.LOG_MESSAGE);
		}
	}
}

100 101 102 103 104
class RunToCursorAction extends EditorAction {

	constructor() {
		super({
			id: 'editor.debug.action.runToCursor',
105
			label: nls.localize('runToCursor', "Run to Cursor"),
106
			alias: 'Debug: Run to Cursor',
I
isidor 已提交
107
			precondition: ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, PanelFocusContext.toNegated(), CONTEXT_DEBUG_STATE.isEqualTo('stopped'), EditorContextKeys.editorTextFocus),
108 109 110 111 112 113 114
			menuOpts: {
				group: 'debug',
				order: 2
			}
		});
	}

115
	public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<void> {
116
		const debugService = accessor.get(IDebugService);
I
isidor 已提交
117 118
		const focusedSession = debugService.getViewModel().focusedSession;
		if (debugService.state !== State.Stopped || !focusedSession) {
I
isidor 已提交
119
			return Promise.resolve(null);
120 121
		}

122
		let breakpointToRemove: IBreakpoint;
I
isidor 已提交
123 124
		const oneTimeListener = focusedSession.onDidChangeState(() => {
			const state = focusedSession.state;
125
			if (state === State.Stopped || state === State.Inactive) {
126 127
				if (breakpointToRemove) {
					debugService.removeBreakpoints(breakpointToRemove.getId());
128 129 130 131 132
				}
				oneTimeListener.dispose();
			}
		});

133 134
		const position = editor.getPosition();
		const uri = editor.getModel().uri;
I
isidor 已提交
135
		const bpExists = !!(debugService.getModel().getBreakpoints({ column: position.column, lineNumber: position.lineNumber, uri }).length);
K
Format  
Kenneth Auchenberg 已提交
136
		return (bpExists ? Promise.resolve(null) : <Promise<any>>debugService.addBreakpoints(uri, [{ lineNumber: position.lineNumber, column: position.column }], 'debugEditorActions.runToCursorAction')).then((breakpoints) => {
137 138 139
			if (breakpoints && breakpoints.length) {
				breakpointToRemove = breakpoints[0];
			}
140 141 142 143 144 145 146 147 148 149 150 151
			debugService.getViewModel().focusedThread.continue();
		});
	}
}

class SelectionToReplAction extends EditorAction {

	constructor() {
		super({
			id: 'editor.debug.action.selectionToRepl',
			label: nls.localize('debugEvaluate', "Debug: Evaluate"),
			alias: 'Debug: Evaluate',
152
			precondition: ContextKeyExpr.and(EditorContextKeys.hasNonEmptySelection, CONTEXT_IN_DEBUG_MODE, EditorContextKeys.editorTextFocus),
153 154 155 156 157 158 159
			menuOpts: {
				group: 'debug',
				order: 0
			}
		});
	}

160
	public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<void> {
161 162 163 164
		const debugService = accessor.get(IDebugService);
		const panelService = accessor.get(IPanelService);

		const text = editor.getModel().getValueInRange(editor.getSelection());
I
isidor 已提交
165 166 167
		const viewModel = debugService.getViewModel();
		const session = viewModel.focusedSession;
		return session.addReplExpression(viewModel.focusedStackFrame, text)
168 169 170 171 172 173 174 175 176 177 178 179
			.then(() => panelService.openPanel(REPL_ID, true))
			.then(_ => void 0);
	}
}

class SelectionToWatchExpressionsAction extends EditorAction {

	constructor() {
		super({
			id: 'editor.debug.action.selectionToWatch',
			label: nls.localize('debugAddToWatch', "Debug: Add to Watch"),
			alias: 'Debug: Add to Watch',
180
			precondition: ContextKeyExpr.and(EditorContextKeys.hasNonEmptySelection, CONTEXT_IN_DEBUG_MODE, EditorContextKeys.editorTextFocus),
181 182 183 184 185 186 187
			menuOpts: {
				group: 'debug',
				order: 1
			}
		});
	}

188
	public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<void> {
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
		const debugService = accessor.get(IDebugService);
		const viewletService = accessor.get(IViewletService);

		const text = editor.getModel().getValueInRange(editor.getSelection());
		return viewletService.openViewlet(VIEWLET_ID).then(() => debugService.addWatchExpression(text));
	}
}

class ShowDebugHoverAction extends EditorAction {

	constructor() {
		super({
			id: 'editor.debug.action.showDebugHover',
			label: nls.localize('showDebugHover', "Debug: Show Hover"),
			alias: 'Debug: Show Hover',
			precondition: CONTEXT_IN_DEBUG_MODE,
			kbOpts: {
206
				kbExpr: EditorContextKeys.editorTextFocus,
A
Alex Dima 已提交
207
				primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_I),
208
				weight: KeybindingWeight.EditorContrib
209 210 211 212
			}
		});
	}

213
	public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<void> {
214 215 216
		const position = editor.getPosition();
		const word = editor.getModel().getWordAtPosition(position);
		if (!word) {
I
isidor 已提交
217
			return Promise.resolve(null);
218 219 220
		}

		const range = new Range(position.lineNumber, position.column, position.lineNumber, word.endColumn);
I
isidor 已提交
221
		return editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showHover(range, true);
222 223
	}
}
224

225
class GoToBreakpointAction extends EditorAction {
226
	constructor(private isNext: boolean, opts: IActionOptions) {
227 228 229
		super(opts);
	}

230
	public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): TPromise<any> {
231 232 233 234
		const debugService = accessor.get(IDebugService);
		const editorService = accessor.get(IEditorService);
		const currentUri = editor.getModel().uri;
		const currentLine = editor.getPosition().lineNumber;
K
Krzysztof Cieslak 已提交
235 236
		//Breakpoints returned from `getBreakpoints` are already sorted.
		const allEnabledBreakpoints = debugService.getModel().getBreakpoints({ enabledOnly: true });
237 238 239 240

		//Try to find breakpoint in current file
		let moveBreakpoint =
			this.isNext
I
isidor 已提交
241 242
				? allEnabledBreakpoints.filter(bp => bp.uri.toString() === currentUri.toString() && bp.lineNumber > currentLine).shift()
				: allEnabledBreakpoints.filter(bp => bp.uri.toString() === currentUri.toString() && bp.lineNumber < currentLine).pop();
243 244 245 246 247

		//Try to find breakpoints in following files
		if (!moveBreakpoint) {
			moveBreakpoint =
				this.isNext
I
isidor 已提交
248 249
					? allEnabledBreakpoints.filter(bp => bp.uri.toString() > currentUri.toString()).shift()
					: allEnabledBreakpoints.filter(bp => bp.uri.toString() < currentUri.toString()).pop();
250 251
		}

I
isidor 已提交
252 253 254
		//Move to first or last possible breakpoint
		if (!moveBreakpoint && allEnabledBreakpoints.length) {
			moveBreakpoint = this.isNext ? allEnabledBreakpoints[0] : allEnabledBreakpoints[allEnabledBreakpoints.length - 1];
255 256 257
		}

		if (moveBreakpoint) {
258
			return openBreakpointSource(moveBreakpoint, false, true, debugService, editorService);
259
		}
260

I
isidor 已提交
261
		return Promise.resolve(null);
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
	}
}

class GoToNextBreakpointAction extends GoToBreakpointAction {
	constructor() {
		super(true, {
			id: 'editor.debug.action.goToNextBreakpoint',
			label: nls.localize('goToNextBreakpoint', "Debug: Go To Next Breakpoint"),
			alias: 'Debug: Go To Next Breakpoint',
			precondition: null
		});
	}
}

class GoToPreviousBreakpointAction extends GoToBreakpointAction {
	constructor() {
		super(false, {
			id: 'editor.debug.action.goToPreviousBreakpoint',
			label: nls.localize('goToPreviousBreakpoint', "Debug: Go To Previous Breakpoint"),
			alias: 'Debug: Go To Previous Breakpoint',
			precondition: null
		});
	}
}

287 288
registerEditorAction(ToggleBreakpointAction);
registerEditorAction(ConditionalBreakpointAction);
289
registerEditorAction(LogPointAction);
290 291 292 293
registerEditorAction(RunToCursorAction);
registerEditorAction(SelectionToReplAction);
registerEditorAction(SelectionToWatchExpressionsAction);
registerEditorAction(ShowDebugHoverAction);
294 295
registerEditorAction(GoToNextBreakpointAction);
registerEditorAction(GoToPreviousBreakpointAction);