gotoError.ts 16.7 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

A
Alex Dima 已提交
6
import * as nls from 'vs/nls';
7 8
import { Emitter } from 'vs/base/common/event';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
9
import { DisposableStore } from 'vs/base/common/lifecycle';
10
import { URI } from 'vs/base/common/uri';
11
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
J
Johannes Rieken 已提交
12
import { IMarker, IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers';
A
Alex Dima 已提交
13
import { Position } from 'vs/editor/common/core/position';
14
import { Range } from 'vs/editor/common/core/range';
A
Alex Dima 已提交
15
import * as editorCommon from 'vs/editor/common/editorCommon';
16
import { registerEditorAction, registerEditorContribution, ServicesAccessor, IActionOptions, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions';
17
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
18
import { IThemeService } from 'vs/platform/theme/common/themeService';
19
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
20
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
21
import { MarkerNavigationWidget } from './gotoErrorWidget';
J
Johannes Rieken 已提交
22
import { compare } from 'vs/base/common/strings';
23
import { binarySearch, find } from 'vs/base/common/arrays';
24
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
25
import { onUnexpectedError } from 'vs/base/common/errors';
26
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
27
import { Action } from 'vs/base/common/actions';
S
Sandeep Somavarapu 已提交
28
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
29
import { isEqual } from 'vs/base/common/resources';
A
Alex Dima 已提交
30

31
class MarkerModel {
E
Erich Gamma 已提交
32

33
	private readonly _editor: ICodeEditor;
E
Erich Gamma 已提交
34 35
	private _markers: IMarker[];
	private _nextIdx: number;
36
	private readonly _toUnbind = new DisposableStore();
E
Erich Gamma 已提交
37
	private _ignoreSelectionChange: boolean;
38
	private readonly _onCurrentMarkerChanged: Emitter<IMarker | undefined>;
M
Matt Bierner 已提交
39
	private readonly _onMarkerSetChanged: Emitter<MarkerModel>;
E
Erich Gamma 已提交
40

A
Alex Dima 已提交
41
	constructor(editor: ICodeEditor, markers: IMarker[]) {
E
Erich Gamma 已提交
42
		this._editor = editor;
P
Peng Lyu 已提交
43
		this._markers = [];
E
Erich Gamma 已提交
44 45 46 47 48 49 50
		this._nextIdx = -1;
		this._ignoreSelectionChange = false;
		this._onCurrentMarkerChanged = new Emitter<IMarker>();
		this._onMarkerSetChanged = new Emitter<MarkerModel>();
		this.setMarkers(markers);

		// listen on editor
51 52
		this._toUnbind.add(this._editor.onDidDispose(() => this.dispose()));
		this._toUnbind.add(this._editor.onDidChangeCursorPosition(() => {
J
Johannes Rieken 已提交
53 54
			if (this._ignoreSelectionChange) {
				return;
E
Erich Gamma 已提交
55
			}
P
Peng Lyu 已提交
56
			if (this.currentMarker && this._editor.getPosition() && Range.containsPosition(this.currentMarker, this._editor.getPosition()!)) {
J
Johannes Rieken 已提交
57 58 59
				return;
			}
			this._nextIdx = -1;
E
Erich Gamma 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72
		}));
	}

	public get onCurrentMarkerChanged() {
		return this._onCurrentMarkerChanged.event;
	}

	public get onMarkerSetChanged() {
		return this._onMarkerSetChanged.event;
	}

	public setMarkers(markers: IMarker[]): void {

J
Johannes Rieken 已提交
73 74 75 76 77 78 79 80
		let oldMarker = this._nextIdx >= 0 ? this._markers[this._nextIdx] : undefined;
		this._markers = markers || [];
		this._markers.sort(MarkerNavigationAction.compareMarker);
		if (!oldMarker) {
			this._nextIdx = -1;
		} else {
			this._nextIdx = Math.max(-1, binarySearch(this._markers, oldMarker, MarkerNavigationAction.compareMarker));
		}
E
Erich Gamma 已提交
81 82 83 84 85 86 87 88 89 90 91 92
		this._onMarkerSetChanged.fire(this);
	}

	public withoutWatchingEditorPosition(callback: () => void): void {
		this._ignoreSelectionChange = true;
		try {
			callback();
		} finally {
			this._ignoreSelectionChange = false;
		}
	}

J
Johannes Rieken 已提交
93 94 95 96
	private _initIdx(fwd: boolean): void {
		let found = false;
		const position = this._editor.getPosition();
		for (let i = 0; i < this._markers.length; i++) {
J
Johannes Rieken 已提交
97 98
			let range = Range.lift(this._markers[i]);

P
Peng Lyu 已提交
99 100
			if (range.isEmpty() && this._editor.getModel()) {
				const word = this._editor.getModel()!.getWordAtPosition(range.getStartPosition());
J
Johannes Rieken 已提交
101 102 103 104 105
				if (word) {
					range = new Range(range.startLineNumber, word.startColumn, range.startLineNumber, word.endColumn);
				}
			}

P
Peng Lyu 已提交
106
			if (position && (range.containsPosition(position) || position.isBeforeOrEqual(range.getStartPosition()))) {
J
Johannes Rieken 已提交
107
				this._nextIdx = i;
E
Erich Gamma 已提交
108
				found = true;
J
Johannes Rieken 已提交
109
				break;
E
Erich Gamma 已提交
110 111 112 113 114 115 116 117 118 119 120
			}
		}
		if (!found) {
			// after the last change
			this._nextIdx = fwd ? 0 : this._markers.length - 1;
		}
		if (this._nextIdx < 0) {
			this._nextIdx = this._markers.length - 1;
		}
	}

P
Peng Lyu 已提交
121
	get currentMarker(): IMarker | undefined {
J
Johannes Rieken 已提交
122 123 124
		return this.canNavigate() ? this._markers[this._nextIdx] : undefined;
	}

125 126 127 128 129 130 131 132 133 134 135
	set currentMarker(marker: IMarker | undefined) {
		const idx = this._nextIdx;
		this._nextIdx = -1;
		if (marker) {
			this._nextIdx = this.indexOf(marker);
		}
		if (this._nextIdx !== idx) {
			this._onCurrentMarkerChanged.fire(marker);
		}
	}

J
Johannes Rieken 已提交
136
	public move(fwd: boolean, inCircles: boolean): boolean {
E
Erich Gamma 已提交
137 138
		if (!this.canNavigate()) {
			this._onCurrentMarkerChanged.fire(undefined);
J
Johannes Rieken 已提交
139
			return !inCircles;
E
Erich Gamma 已提交
140 141
		}

J
Johannes Rieken 已提交
142 143 144
		let oldIdx = this._nextIdx;
		let atEdge = false;

E
Erich Gamma 已提交
145
		if (this._nextIdx === -1) {
J
Johannes Rieken 已提交
146
			this._initIdx(fwd);
J
Johannes Rieken 已提交
147

E
Erich Gamma 已提交
148
		} else if (fwd) {
J
Johannes Rieken 已提交
149 150 151 152 153 154 155 156 157 158 159 160
			if (inCircles || this._nextIdx + 1 < this._markers.length) {
				this._nextIdx = (this._nextIdx + 1) % this._markers.length;
			} else {
				atEdge = true;
			}

		} else if (!fwd) {
			if (inCircles || this._nextIdx > 0) {
				this._nextIdx = (this._nextIdx - 1 + this._markers.length) % this._markers.length;
			} else {
				atEdge = true;
			}
E
Erich Gamma 已提交
161 162
		}

J
Johannes Rieken 已提交
163
		if (oldIdx !== this._nextIdx) {
164 165 166
			const marker = this._markers[this._nextIdx];
			this._onCurrentMarkerChanged.fire(marker);
		}
E
Erich Gamma 已提交
167

J
Johannes Rieken 已提交
168
		return atEdge;
E
Erich Gamma 已提交
169 170
	}

171 172
	public canNavigate(): boolean {
		return this._markers.length > 0;
E
Erich Gamma 已提交
173 174
	}

P
Peng Lyu 已提交
175
	public findMarkerAtPosition(pos: Position): IMarker | undefined {
176
		return find(this._markers, marker => Range.containsPosition(marker, pos));
E
Erich Gamma 已提交
177 178
	}

J
Johannes Rieken 已提交
179 180 181 182 183 184 185
	public get total() {
		return this._markers.length;
	}

	public indexOf(marker: IMarker): number {
		return 1 + this._markers.indexOf(marker);
	}
186 187

	public dispose(): void {
188
		this._toUnbind.dispose();
189
	}
E
Erich Gamma 已提交
190 191
}

192
export class MarkerController implements editorCommon.IEditorContribution {
E
Erich Gamma 已提交
193

194
	public static readonly ID = 'editor.contrib.markerController';
E
Erich Gamma 已提交
195

196
	public static get(editor: ICodeEditor): MarkerController {
A
Alex Dima 已提交
197
		return editor.getContribution<MarkerController>(MarkerController.ID);
E
Erich Gamma 已提交
198 199
	}

200
	private readonly _editor: ICodeEditor;
201 202
	private _model: MarkerModel | null = null;
	private _widget: MarkerNavigationWidget | null = null;
203
	private readonly _widgetVisible: IContextKey<boolean>;
204
	private readonly _disposeOnClose = new DisposableStore();
E
Erich Gamma 已提交
205

206
	constructor(
207
		editor: ICodeEditor,
208 209
		@IMarkerService private readonly _markerService: IMarkerService,
		@IContextKeyService private readonly _contextKeyService: IContextKeyService,
210
		@IThemeService private readonly _themeService: IThemeService,
S
Sandeep Somavarapu 已提交
211 212
		@ICodeEditorService private readonly _editorService: ICodeEditorService,
		@IKeybindingService private readonly _keybindingService: IKeybindingService
213 214
	) {
		this._editor = editor;
215
		this._widgetVisible = CONTEXT_MARKERS_NAVIGATION_VISIBLE.bindTo(this._contextKeyService);
E
Erich Gamma 已提交
216 217 218 219
	}

	public dispose(): void {
		this._cleanUp();
220
		this._disposeOnClose.dispose();
E
Erich Gamma 已提交
221 222 223
	}

	private _cleanUp(): void {
224
		this._widgetVisible.reset();
225
		this._disposeOnClose.clear();
226
		this._widget = null;
E
Erich Gamma 已提交
227 228 229 230 231 232 233 234 235
		this._model = null;
	}

	public getOrCreateModel(): MarkerModel {

		if (this._model) {
			return this._model;
		}

J
Johannes Rieken 已提交
236
		const markers = this._getMarkers();
237
		this._model = new MarkerModel(this._editor, markers);
238
		this._markerService.onMarkerChanged(this._onMarkerChanged, this, this._disposeOnClose);
E
Erich Gamma 已提交
239

S
Sandeep Somavarapu 已提交
240 241
		const prevMarkerKeybinding = this._keybindingService.lookupKeybinding(PrevMarkerAction.ID);
		const nextMarkerKeybinding = this._keybindingService.lookupKeybinding(NextMarkerAction.ID);
242
		const actions = [
M
Miguel Solorio 已提交
243 244
			new Action(PrevMarkerAction.ID, PrevMarkerAction.LABEL + (prevMarkerKeybinding ? ` (${prevMarkerKeybinding.getLabel()})` : ''), 'show-previous-problem codicon-chevron-up', this._model.canNavigate(), async () => { if (this._model) { this._model.move(false, true); } }),
			new Action(NextMarkerAction.ID, NextMarkerAction.LABEL + (nextMarkerKeybinding ? ` (${nextMarkerKeybinding.getLabel()})` : ''), 'show-next-problem codicon-chevron-down', this._model.canNavigate(), async () => { if (this._model) { this._model.move(true, true); } })
245 246
		];
		this._widget = new MarkerNavigationWidget(this._editor, actions, this._themeService);
247
		this._widgetVisible.set(true);
S
Sandeep Somavarapu 已提交
248
		this._widget.onDidClose(() => this._cleanUp(), this, this._disposeOnClose);
249

250 251 252 253 254 255
		this._disposeOnClose.add(this._model);
		this._disposeOnClose.add(this._widget);
		for (const action of actions) {
			this._disposeOnClose.add(action);
		}
		this._disposeOnClose.add(this._widget.onDidSelectRelatedInformation(related => {
256
			this._editorService.openCodeEditor({
257 258
				resource: related.resource,
				options: { pinned: true, revealIfOpened: true, selection: Range.lift(related).collapseToStart() }
259
			}, this._editor).then(undefined, onUnexpectedError);
260 261
			this.closeMarkersNavigation(false);
		}));
262
		this._disposeOnClose.add(this._editor.onDidChangeModel(() => this._cleanUp()));
263

264
		this._disposeOnClose.add(this._model.onCurrentMarkerChanged(marker => {
P
Peng Lyu 已提交
265
			if (!marker || !this._model) {
266 267 268
				this._cleanUp();
			} else {
				this._model.withoutWatchingEditorPosition(() => {
P
Peng Lyu 已提交
269 270 271
					if (!this._widget || !this._model) {
						return;
					}
272 273 274 275
					this._widget.showAtMarker(marker, this._model.indexOf(marker), this._model.total);
				});
			}
		}));
276
		this._disposeOnClose.add(this._model.onMarkerSetChanged(() => {
P
Peng Lyu 已提交
277 278 279 280
			if (!this._widget || !this._widget.position || !this._model) {
				return;
			}

281 282 283 284 285 286 287
			const marker = this._model.findMarkerAtPosition(this._widget.position);
			if (marker) {
				this._widget.updateMarker(marker);
			} else {
				this._widget.showStale();
			}
		}));
E
Erich Gamma 已提交
288

289 290
		return this._model;
	}
E
Erich Gamma 已提交
291

292
	public closeMarkersNavigation(focusEditor: boolean = true): void {
293
		this._cleanUp();
294 295 296
		if (focusEditor) {
			this._editor.focus();
		}
E
Erich Gamma 已提交
297 298
	}

299 300 301 302 303
	public show(marker: IMarker): void {
		const model = this.getOrCreateModel();
		model.currentMarker = marker;
	}

E
Erich Gamma 已提交
304
	private _onMarkerChanged(changedResources: URI[]): void {
305
		const editorModel = this._editor.getModel();
P
Peng Lyu 已提交
306 307 308 309 310 311 312 313
		if (!editorModel) {
			return;
		}

		if (!this._model) {
			return;
		}

314
		if (!changedResources.some(r => isEqual(editorModel.uri, r))) {
E
Erich Gamma 已提交
315 316 317 318 319 320
			return;
		}
		this._model.setMarkers(this._getMarkers());
	}

	private _getMarkers(): IMarker[] {
P
Peng Lyu 已提交
321 322 323 324 325
		let model = this._editor.getModel();
		if (!model) {
			return [];
		}

326
		return this._markerService.read({
P
Peng Lyu 已提交
327
			resource: model.uri,
J
Johannes Rieken 已提交
328
			severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info
329
		});
E
Erich Gamma 已提交
330 331 332
	}
}

J
Johannes Rieken 已提交
333 334
class MarkerNavigationAction extends EditorAction {

335
	private readonly _isNext: boolean;
J
Johannes Rieken 已提交
336

337
	private readonly _multiFile: boolean;
338 339

	constructor(next: boolean, multiFile: boolean, opts: IActionOptions) {
J
Johannes Rieken 已提交
340 341
		super(opts);
		this._isNext = next;
342
		this._multiFile = multiFile;
J
Johannes Rieken 已提交
343 344
	}

J
Johannes Rieken 已提交
345
	public run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
J
Johannes Rieken 已提交
346 347

		const markerService = accessor.get(IMarkerService);
348
		const editorService = accessor.get(ICodeEditorService);
J
Johannes Rieken 已提交
349 350
		const controller = MarkerController.get(editor);
		if (!controller) {
R
Rob Lourens 已提交
351
			return Promise.resolve(undefined);
J
Johannes Rieken 已提交
352 353 354
		}

		const model = controller.getOrCreateModel();
355 356
		const atEdge = model.move(this._isNext, !this._multiFile);
		if (!atEdge || !this._multiFile) {
R
Rob Lourens 已提交
357
			return Promise.resolve(undefined);
J
Johannes Rieken 已提交
358 359 360
		}

		// try with the next/prev file
J
Johannes Rieken 已提交
361
		let markers = markerService.read({ severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info }).sort(MarkerNavigationAction.compareMarker);
362
		if (markers.length === 0) {
R
Rob Lourens 已提交
363
			return Promise.resolve(undefined);
P
Peng Lyu 已提交
364 365
		}

366
		const editorModel = editor.getModel();
P
Peng Lyu 已提交
367
		if (!editorModel) {
R
Rob Lourens 已提交
368
			return Promise.resolve(undefined);
369 370
		}

P
Peng Lyu 已提交
371
		let oldMarker = model.currentMarker || <IMarker>{ resource: editorModel!.uri, severity: MarkerSeverity.Error, startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 };
J
Johannes Rieken 已提交
372 373 374 375 376 377 378 379 380 381 382 383
		let idx = binarySearch(markers, oldMarker, MarkerNavigationAction.compareMarker);
		if (idx < 0) {
			// find best match...
			idx = ~idx;
			idx %= markers.length;
		} else if (this._isNext) {
			idx = (idx + 1) % markers.length;
		} else {
			idx = (idx + markers.length - 1) % markers.length;
		}

		let newMarker = markers[idx];
384
		if (isEqual(newMarker.resource, editorModel.uri)) {
J
Johannes Rieken 已提交
385 386 387
			// the next `resource` is this resource which
			// means we cycle within this file
			model.move(this._isNext, true);
R
Rob Lourens 已提交
388
			return Promise.resolve(undefined);
J
Johannes Rieken 已提交
389 390 391 392 393 394
		}

		// close the widget for this editor-instance, open the resource
		// for the next marker and re-start marker navigation in there
		controller.closeMarkersNavigation();

395
		return editorService.openCodeEditor({
J
Johannes Rieken 已提交
396 397
			resource: newMarker.resource,
			options: { pinned: false, revealIfOpened: true, revealInCenterIfOutsideViewport: true, selection: newMarker }
398
		}, editor).then(editor => {
399
			if (!editor) {
J
Johannes Rieken 已提交
400 401
				return undefined;
			}
402
			return editor.getAction(this.id).run();
403
		});
J
Johannes Rieken 已提交
404 405 406 407 408
	}

	static compareMarker(a: IMarker, b: IMarker): number {
		let res = compare(a.resource.toString(), b.resource.toString());
		if (res === 0) {
J
Johannes Rieken 已提交
409
			res = MarkerSeverity.compare(a.severity, b.severity);
J
Johannes Rieken 已提交
410 411 412 413 414 415 416 417
		}
		if (res === 0) {
			res = Range.compareRangesUsingStarts(a, b);
		}
		return res;
	}
}

S
Sandeep Somavarapu 已提交
418
export class NextMarkerAction extends MarkerNavigationAction {
419 420
	static ID: string = 'editor.action.marker.next';
	static LABEL: string = nls.localize('markerAction.next.label', "Go to Next Problem (Error, Warning, Info)");
A
Alex Dima 已提交
421
	constructor() {
422
		super(true, false, {
423 424
			id: NextMarkerAction.ID,
			label: NextMarkerAction.LABEL,
425
			alias: 'Go to Next Problem (Error, Warning, Info)',
S
Sandeep Somavarapu 已提交
426 427
			precondition: EditorContextKeys.writable,
			kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Alt | KeyCode.F8, weight: KeybindingWeight.EditorContrib }
428 429 430 431 432
		});
	}
}

class PrevMarkerAction extends MarkerNavigationAction {
433 434
	static ID: string = 'editor.action.marker.prev';
	static LABEL: string = nls.localize('markerAction.previous.label', "Go to Previous Problem (Error, Warning, Info)");
435 436
	constructor() {
		super(false, false, {
437 438
			id: PrevMarkerAction.ID,
			label: PrevMarkerAction.LABEL,
439
			alias: 'Go to Previous Problem (Error, Warning, Info)',
S
Sandeep Somavarapu 已提交
440 441
			precondition: EditorContextKeys.writable,
			kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F8, weight: KeybindingWeight.EditorContrib }
442 443 444 445 446 447 448 449 450
		});
	}
}

class NextMarkerInFilesAction extends MarkerNavigationAction {
	constructor() {
		super(true, true, {
			id: 'editor.action.marker.nextInFiles',
			label: nls.localize('markerAction.nextInFiles.label', "Go to Next Problem in Files (Error, Warning, Info)"),
451
			alias: 'Go to Next Problem in Files (Error, Warning, Info)',
452
			precondition: EditorContextKeys.writable,
453
			kbOpts: {
454
				kbExpr: EditorContextKeys.focus,
A
Alex Dima 已提交
455
				primary: KeyCode.F8,
456
				weight: KeybindingWeight.EditorContrib
457 458
			}
		});
E
Erich Gamma 已提交
459 460 461
	}
}

462
class PrevMarkerInFilesAction extends MarkerNavigationAction {
A
Alex Dima 已提交
463
	constructor() {
464 465 466
		super(false, true, {
			id: 'editor.action.marker.prevInFiles',
			label: nls.localize('markerAction.previousInFiles.label', "Go to Previous Problem in Files (Error, Warning, Info)"),
467
			alias: 'Go to Previous Problem in Files (Error, Warning, Info)',
468
			precondition: EditorContextKeys.writable,
469
			kbOpts: {
470
				kbExpr: EditorContextKeys.focus,
A
Alex Dima 已提交
471
				primary: KeyMod.Shift | KeyCode.F8,
472
				weight: KeybindingWeight.EditorContrib
473 474
			}
		});
E
Erich Gamma 已提交
475 476 477
	}
}

478
registerEditorContribution(MarkerController.ID, MarkerController);
479 480
registerEditorAction(NextMarkerAction);
registerEditorAction(PrevMarkerAction);
481 482
registerEditorAction(NextMarkerInFilesAction);
registerEditorAction(PrevMarkerInFilesAction);
483

J
Johannes Rieken 已提交
484
const CONTEXT_MARKERS_NAVIGATION_VISIBLE = new RawContextKey<boolean>('markersNavigationVisible', false);
A
Alex Dima 已提交
485

A
Alex Dima 已提交
486
const MarkerCommand = EditorCommand.bindToContribution<MarkerController>(MarkerController.get);
E
Erich Gamma 已提交
487

488
registerEditorCommand(new MarkerCommand({
489 490 491 492
	id: 'closeMarkersNavigation',
	precondition: CONTEXT_MARKERS_NAVIGATION_VISIBLE,
	handler: x => x.closeMarkersNavigation(),
	kbOpts: {
493
		weight: KeybindingWeight.EditorContrib + 50,
494
		kbExpr: EditorContextKeys.focus,
A
Alex Dima 已提交
495 496 497
		primary: KeyCode.Escape,
		secondary: [KeyMod.Shift | KeyCode.Escape]
	}
498
}));
499 500 501 502 503

// Go to menu
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
	group: '6_problem_nav',
	command: {
504
		id: 'editor.action.marker.nextInFiles',
505 506 507 508 509 510 511 512
		title: nls.localize({ key: 'miGotoNextProblem', comment: ['&& denotes a mnemonic'] }, "Next &&Problem")
	},
	order: 1
});

MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
	group: '6_problem_nav',
	command: {
513
		id: 'editor.action.marker.prevInFiles',
514 515 516
		title: nls.localize({ key: 'miGotoPreviousProblem', comment: ['&& denotes a mnemonic'] }, "Previous &&Problem")
	},
	order: 2
M
Miguel Solorio 已提交
517
});