Align MultiEditorAction with MultiCommand

This commit is contained in:
Alex Dima
2021-02-26 16:08:41 +01:00
committed by Alexandru Dima
parent 453e2793b2
commit 60222b710d
6 changed files with 195 additions and 176 deletions

View File

@@ -339,13 +339,13 @@ export abstract class EditorAction extends EditorCommand {
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void>;
}
export abstract class MultiEditorAction extends EditorAction {
export class MultiEditorAction extends EditorAction {
private readonly _implementations: [number, CommandImplementation][] = [];
constructor(opts: IActionOptions) {
super(opts);
}
/**
* A higher priority gets to be looked at first
*/
public addImplementation(priority: number, implementation: CommandImplementation): IDisposable {
this._implementations.push([priority, implementation]);
this._implementations.sort((a, b) => b[0] - a[0]);
@@ -361,20 +361,18 @@ export abstract class MultiEditorAction extends EditorAction {
};
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void> {
this.reportTelemetry(accessor, editor);
public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void> {
for (const impl of this._implementations) {
if (impl[1](accessor, args)) {
return;
const result = impl[1](accessor, args);
if (result) {
if (typeof result === 'boolean') {
return;
}
return result;
}
}
return this.run(accessor, editor, args || {});
}
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void>;
}
//#endregion EditorAction

View File

@@ -26,6 +26,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
const SEARCH_STRING_MAX_LENGTH = 524288;
@@ -483,43 +484,44 @@ export class FindController extends CommonFindController implements IFindControl
}
}
export class StartFindAction extends MultiEditorAction {
constructor() {
super({
id: FIND_IDS.StartFindAction,
label: nls.localize('startFindAction', "Find"),
alias: 'Find',
precondition: ContextKeyExpr.or(EditorContextKeys.focus, ContextKeyExpr.has('editorIsOpen')),
kbOpts: {
kbExpr: null,
primary: KeyMod.CtrlCmd | KeyCode.KEY_F,
weight: KeybindingWeight.EditorContrib
},
menuOpts: {
menuId: MenuId.MenubarEditMenu,
group: '3_find',
title: nls.localize({ key: 'miFind', comment: ['&& denotes a mnemonic'] }, "&&Find"),
order: 1
}
});
export const StartFindAction = registerMultiEditorAction(new MultiEditorAction({
id: FIND_IDS.StartFindAction,
label: nls.localize('startFindAction', "Find"),
alias: 'Find',
precondition: ContextKeyExpr.or(EditorContextKeys.focus, ContextKeyExpr.has('editorIsOpen')),
kbOpts: {
kbExpr: null,
primary: KeyMod.CtrlCmd | KeyCode.KEY_F,
weight: KeybindingWeight.EditorContrib
},
menuOpts: {
menuId: MenuId.MenubarEditMenu,
group: '3_find',
title: nls.localize({ key: 'miFind', comment: ['&& denotes a mnemonic'] }, "&&Find"),
order: 1
}
}));
public async run(accessor: ServicesAccessor | null, editor: ICodeEditor): Promise<void> {
let controller = CommonFindController.get(editor);
if (controller) {
await controller.start({
forceRevealReplace: false,
seedSearchStringFromSelection: editor.getOption(EditorOption.find).seedSearchStringFromSelection ? 'single' : 'none',
seedSearchStringFromGlobalClipboard: editor.getOption(EditorOption.find).globalFindClipboard,
shouldFocus: FindStartFocusAction.FocusFindInput,
shouldAnimate: true,
updateSearchScope: false,
loop: editor.getOption(EditorOption.find).loop
});
}
StartFindAction.addImplementation(0, (accessor: ServicesAccessor, args: any): boolean | Promise<void> => {
const codeEditorService = accessor.get(ICodeEditorService);
const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
if (!editor) {
return false;
}
}
const controller = CommonFindController.get(editor);
if (!controller) {
return false;
}
return controller.start({
forceRevealReplace: false,
seedSearchStringFromSelection: editor.getOption(EditorOption.find).seedSearchStringFromSelection ? 'single' : 'none',
seedSearchStringFromGlobalClipboard: editor.getOption(EditorOption.find).globalFindClipboard,
shouldFocus: FindStartFocusAction.FocusFindInput,
shouldAnimate: true,
updateSearchScope: false,
loop: editor.getOption(EditorOption.find).loop
});
});
export class StartFindWithSelectionAction extends EditorAction {
@@ -744,71 +746,66 @@ export class PreviousSelectionMatchFindAction extends SelectionMatchFindAction {
}
}
export class StartFindReplaceAction extends MultiEditorAction {
export const StartFindReplaceAction = registerMultiEditorAction(new MultiEditorAction({
id: FIND_IDS.StartFindReplaceAction,
label: nls.localize('startReplace', "Replace"),
alias: 'Replace',
precondition: ContextKeyExpr.or(EditorContextKeys.focus, ContextKeyExpr.has('editorIsOpen')),
kbOpts: {
kbExpr: null,
primary: KeyMod.CtrlCmd | KeyCode.KEY_H,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_F },
weight: KeybindingWeight.EditorContrib
},
menuOpts: {
menuId: MenuId.MenubarEditMenu,
group: '3_find',
title: nls.localize({ key: 'miReplace', comment: ['&& denotes a mnemonic'] }, "&&Replace"),
order: 2
}
}));
constructor() {
super({
id: FIND_IDS.StartFindReplaceAction,
label: nls.localize('startReplace', "Replace"),
alias: 'Replace',
precondition: ContextKeyExpr.or(EditorContextKeys.focus, ContextKeyExpr.has('editorIsOpen')),
kbOpts: {
kbExpr: null,
primary: KeyMod.CtrlCmd | KeyCode.KEY_H,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_F },
weight: KeybindingWeight.EditorContrib
},
menuOpts: {
menuId: MenuId.MenubarEditMenu,
group: '3_find',
title: nls.localize({ key: 'miReplace', comment: ['&& denotes a mnemonic'] }, "&&Replace"),
order: 2
}
});
StartFindReplaceAction.addImplementation(0, (accessor: ServicesAccessor, args: any): boolean | Promise<void> => {
const codeEditorService = accessor.get(ICodeEditorService);
const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
if (!editor || !editor.hasModel() || editor.getOption(EditorOption.readOnly)) {
return false;
}
const controller = CommonFindController.get(editor);
if (!controller) {
return false;
}
public async run(accessor: ServicesAccessor | null, editor: ICodeEditor): Promise<void> {
if (!editor.hasModel() || editor.getOption(EditorOption.readOnly)) {
return;
}
const currentSelection = editor.getSelection();
const findInputFocused = controller.isFindInputFocused();
// we only seed search string from selection when the current selection is single line and not empty,
// + the find input is not focused
const seedSearchStringFromSelection = !currentSelection.isEmpty()
&& currentSelection.startLineNumber === currentSelection.endLineNumber && editor.getOption(EditorOption.find).seedSearchStringFromSelection
&& !findInputFocused;
/*
* if the existing search string in find widget is empty and we don't seed search string from selection, it means the Find Input is still empty, so we should focus the Find Input instead of Replace Input.
let controller = CommonFindController.get(editor);
let currentSelection = editor.getSelection();
let findInputFocused = controller.isFindInputFocused();
// we only seed search string from selection when the current selection is single line and not empty,
// + the find input is not focused
let seedSearchStringFromSelection = !currentSelection.isEmpty()
&& currentSelection.startLineNumber === currentSelection.endLineNumber && editor.getOption(EditorOption.find).seedSearchStringFromSelection
&& !findInputFocused;
/*
* if the existing search string in find widget is empty and we don't seed search string from selection, it means the Find Input is still empty, so we should focus the Find Input instead of Replace Input.
* findInputFocused true -> seedSearchStringFromSelection false, FocusReplaceInput
* findInputFocused false, seedSearchStringFromSelection true FocusReplaceInput
* findInputFocused false seedSearchStringFromSelection false FocusFindInput
*/
const shouldFocus = (findInputFocused || seedSearchStringFromSelection) ?
FindStartFocusAction.FocusReplaceInput : FindStartFocusAction.FocusFindInput;
* findInputFocused true -> seedSearchStringFromSelection false, FocusReplaceInput
* findInputFocused false, seedSearchStringFromSelection true FocusReplaceInput
* findInputFocused false seedSearchStringFromSelection false FocusFindInput
*/
let shouldFocus = (findInputFocused || seedSearchStringFromSelection) ?
FindStartFocusAction.FocusReplaceInput : FindStartFocusAction.FocusFindInput;
if (controller) {
await controller.start({
forceRevealReplace: true,
seedSearchStringFromSelection: seedSearchStringFromSelection ? 'single' : 'none',
seedSearchStringFromGlobalClipboard: editor.getOption(EditorOption.find).seedSearchStringFromSelection,
shouldFocus: shouldFocus,
shouldAnimate: true,
updateSearchScope: false,
loop: editor.getOption(EditorOption.find).loop
});
}
}
}
return controller.start({
forceRevealReplace: true,
seedSearchStringFromSelection: seedSearchStringFromSelection ? 'single' : 'none',
seedSearchStringFromGlobalClipboard: editor.getOption(EditorOption.find).seedSearchStringFromSelection,
shouldFocus: shouldFocus,
shouldAnimate: true,
updateSearchScope: false,
loop: editor.getOption(EditorOption.find).loop
});
});
registerEditorContribution(CommonFindController.ID, FindController);
export const EditorStartFindAction = new StartFindAction();
registerMultiEditorAction(EditorStartFindAction);
registerEditorAction(StartFindWithSelectionAction);
registerEditorAction(NextMatchFindAction);
registerEditorAction(NextMatchFindAction2);
@@ -816,8 +813,6 @@ registerEditorAction(PreviousMatchFindAction);
registerEditorAction(PreviousMatchFindAction2);
registerEditorAction(NextSelectionMatchFindAction);
registerEditorAction(PreviousSelectionMatchFindAction);
export const EditorStartFindReplaceAction = new StartFindReplaceAction();
registerMultiEditorAction(EditorStartFindReplaceAction);
const FindCommand = EditorCommand.bindToContribution<CommonFindController>(CommonFindController.get);

View File

@@ -8,6 +8,7 @@ import { Delayer } from 'vs/base/common/async';
import { Event } from 'vs/base/common/event';
import * as platform from 'vs/base/common/platform';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction } from 'vs/editor/browser/editorExtensions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
@@ -17,6 +18,7 @@ import { CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel';
import { withAsyncTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IStorageService } from 'vs/platform/storage/common/storage';
@@ -55,10 +57,16 @@ function fromSelection(slc: Selection): number[] {
return [slc.startLineNumber, slc.startColumn, slc.endLineNumber, slc.endColumn];
}
function executeAction(instantiationService: IInstantiationService, editor: ICodeEditor, action: EditorAction, args?: any): Promise<void> {
return instantiationService.invokeFunction((accessor) => {
return Promise.resolve(action.runEditorCommand(accessor, editor, args));
});
}
suite('FindController', async () => {
let queryState: { [key: string]: any; } = {};
const queryState: { [key: string]: any; } = {};
let clipboardState = '';
let serviceCollection = new ServiceCollection();
const serviceCollection = new ServiceCollection();
serviceCollection.set(IStorageService, {
_serviceBrand: undefined,
onDidChangeTarget: Event.None,
@@ -164,16 +172,15 @@ suite('FindController', async () => {
'ABC',
'XYZ',
'ABC'
], { serviceCollection: serviceCollection }, async (editor) => {
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
clipboardState = '';
// The cursor is at the very top, of the file, at the first ABC
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let findState = findController.getState();
let startFindAction = new StartFindAction();
let nextMatchFindAction = new NextMatchFindAction();
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findState = findController.getState();
const nextMatchFindAction = new NextMatchFindAction();
// I hit Ctrl+F to show the Find dialog
await startFindAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindAction);
// I type ABC.
findState.change({ searchString: 'A' }, true);
@@ -221,8 +228,8 @@ suite('FindController', async () => {
'import nls = require(\'vs/nls\');'
], { serviceCollection: serviceCollection }, async (editor) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let nextMatchFindAction = new NextMatchFindAction();
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const nextMatchFindAction = new NextMatchFindAction();
editor.setPosition({
lineNumber: 1,
@@ -244,16 +251,15 @@ suite('FindController', async () => {
'var x = (3 * 5)',
'var y = (3 * 5)',
'var z = (3 * 5)',
], { serviceCollection: serviceCollection }, async (editor) => {
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let startFindAction = new StartFindAction();
let nextMatchFindAction = new NextMatchFindAction();
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const nextMatchFindAction = new NextMatchFindAction();
editor.setSelection(new Selection(1, 9, 1, 13));
findController.toggleRegex();
await startFindAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindAction);
await nextMatchFindAction.run(null, editor);
assert.deepStrictEqual(fromSelection(editor.getSelection()!), [2, 9, 2, 13]);
@@ -268,11 +274,10 @@ suite('FindController', async () => {
test('issue #41027: Don\'t replace find input value on replace action if find input is active', async () => {
await withAsyncTestCodeEditor([
'test',
], { serviceCollection: serviceCollection }, async (editor) => {
let testRegexString = 'tes.';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let nextMatchFindAction = new NextMatchFindAction();
let startFindReplaceAction = new StartFindReplaceAction();
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
const testRegexString = 'tes.';
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const nextMatchFindAction = new NextMatchFindAction();
findController.toggleRegex();
findController.setSearchString(testRegexString);
@@ -286,7 +291,7 @@ suite('FindController', async () => {
loop: true
});
await nextMatchFindAction.run(null, editor);
await startFindReplaceAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindReplaceAction);
assert.strictEqual(findController.getState().searchString, testRegexString);
@@ -301,7 +306,7 @@ suite('FindController', async () => {
'var z = (3 * 5)',
], { serviceCollection: serviceCollection }, async (editor) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
await findController.start({
forceRevealReplace: false,
seedSearchStringFromSelection: 'none',
@@ -328,12 +333,11 @@ suite('FindController', async () => {
test('issue #18111: Regex replace with single space replaces with no space', async () => {
await withAsyncTestCodeEditor([
'HRESULT OnAmbientPropertyChange(DISPID dispid);'
], { serviceCollection: serviceCollection }, async (editor) => {
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let startFindAction = new StartFindAction();
await startFindAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindAction);
findController.getState().change({ searchString: '\\b\\s{3}\\b', replaceString: ' ', isRegex: true }, false);
findController.moveToNextMatch();
@@ -355,12 +359,11 @@ suite('FindController', async () => {
'',
'line2',
'line3'
], { serviceCollection: serviceCollection }, async (editor) => {
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let startFindAction = new StartFindAction();
await startFindAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindAction);
findController.getState().change({ searchString: '^', replaceString: 'x', isRegex: true }, false);
findController.moveToNextMatch();
@@ -384,8 +387,8 @@ suite('FindController', async () => {
'([funny]'
], { serviceCollection: serviceCollection }, async (editor) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let nextSelectionMatchFindAction = new NextSelectionMatchFindAction();
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const nextSelectionMatchFindAction = new NextSelectionMatchFindAction();
// toggle regex
findController.getState().change({ isRegex: true }, false);
@@ -409,14 +412,13 @@ suite('FindController', async () => {
'([funny]',
'',
'([funny]'
], { serviceCollection: serviceCollection }, async (editor) => {
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let startFindAction = new StartFindAction();
let nextSelectionMatchFindAction = new NextSelectionMatchFindAction();
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const nextSelectionMatchFindAction = new NextSelectionMatchFindAction();
// cmd+f - open find widget
await startFindAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindAction);
// toggle regex
findController.getState().change({ isRegex: true }, false);
@@ -442,21 +444,20 @@ suite('FindController', async () => {
'XYZ',
'ABC',
'ABC'
], { serviceCollection: serviceCollection }, async (editor) => {
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let startFindAction = new StartFindAction();
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
// change selection
editor.setSelection(new Selection(1, 1, 1, 1));
// cmd+f - open find widget
await startFindAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindAction);
editor.setSelection(new Selection(1, 1, 2, 4));
let startFindWithSelectionAction = new StartFindWithSelectionAction();
const startFindWithSelectionAction = new StartFindWithSelectionAction();
await startFindWithSelectionAction.run(null, editor);
let findState = findController.getState();
const findState = findController.getState();
assert.deepStrictEqual(findState.searchString.split(/\r\n|\r|\n/g), ['ABC', 'ABC']);
@@ -476,13 +477,13 @@ suite('FindController', async () => {
'ABC'
], { serviceCollection: serviceCollection }, async (editor) => {
clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
editor.setSelection(new Selection(1, 2, 1, 2));
let startFindWithSelectionAction = new StartFindWithSelectionAction();
const startFindWithSelectionAction = new StartFindWithSelectionAction();
startFindWithSelectionAction.run(null, editor);
let findState = findController.getState();
const findState = findController.getState();
assert.deepStrictEqual(findState.searchString, 'ABC');
findController.dispose();
});
@@ -494,7 +495,7 @@ suite('FindController query options persistence', async () => {
queryState['editor.isRegex'] = false;
queryState['editor.matchCase'] = false;
queryState['editor.wholeWord'] = false;
let serviceCollection = new ServiceCollection();
const serviceCollection = new ServiceCollection();
serviceCollection.set(IStorageService, {
_serviceBrand: undefined,
onDidChangeTarget: Event.None,
@@ -518,15 +519,14 @@ suite('FindController query options persistence', async () => {
'ABC',
'XYZ',
'ABC'
], { serviceCollection: serviceCollection }, async (editor) => {
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
queryState = { 'editor.isRegex': false, 'editor.matchCase': true, 'editor.wholeWord': false };
// The cursor is at the very top, of the file, at the first ABC
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let findState = findController.getState();
let startFindAction = new StartFindAction();
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findState = findController.getState();
// I hit Ctrl+F to show the Find dialog
await startFindAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindAction);
// I type ABC.
findState.change({ searchString: 'ABC' }, true);
@@ -545,15 +545,14 @@ suite('FindController query options persistence', async () => {
'AB',
'XYZ',
'ABC'
], { serviceCollection: serviceCollection }, async (editor) => {
], { serviceCollection: serviceCollection }, async (editor, _, instantiationService) => {
queryState = { 'editor.isRegex': false, 'editor.matchCase': false, 'editor.wholeWord': true };
// The cursor is at the very top, of the file, at the first ABC
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
let findState = findController.getState();
let startFindAction = new StartFindAction();
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findState = findController.getState();
// I hit Ctrl+F to show the Find dialog
await startFindAction.run(null, editor);
await executeAction(instantiationService, editor, StartFindAction);
// I type AB.
findState.change({ searchString: 'AB' }, true);
@@ -573,7 +572,7 @@ suite('FindController query options persistence', async () => {
], { serviceCollection: serviceCollection }, async (editor) => {
queryState = { 'editor.isRegex': false, 'editor.matchCase': false, 'editor.wholeWord': true };
// The cursor is at the very top, of the file, at the first ABC
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
findController.toggleRegex();
assert.strictEqual(queryState['editor.isRegex'], true);
@@ -588,7 +587,7 @@ suite('FindController query options persistence', async () => {
'var z = (3 * 5)',
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, async (editor) => {
// clipboardState = '';
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findConfig: IFindStartOptions = {
forceRevealReplace: false,
seedSearchStringFromSelection: 'none',
@@ -619,7 +618,7 @@ suite('FindController query options persistence', async () => {
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, async (editor) => {
// clipboardState = '';
editor.setSelection(new Range(1, 2, 1, 2));
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
await findController.start({
forceRevealReplace: false,
@@ -643,7 +642,7 @@ suite('FindController query options persistence', async () => {
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, async (editor) => {
// clipboardState = '';
editor.setSelection(new Range(1, 2, 1, 3));
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
await findController.start({
forceRevealReplace: false,
@@ -668,7 +667,7 @@ suite('FindController query options persistence', async () => {
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'multiline', globalFindClipboard: false } }, async (editor) => {
// clipboardState = '';
editor.setSelection(new Range(1, 6, 2, 1));
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
const findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
await findController.start({
forceRevealReplace: false,

View File

@@ -23,6 +23,8 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
@@ -41,6 +43,13 @@ export class TestCodeEditor extends CodeEditorWidget implements ICodeEditor {
// Never create a view
return [null! as View, false];
}
private _hasTextFocus = false;
public setHasTextFocus(hasTextFocus: boolean): void {
this._hasTextFocus = hasTextFocus;
}
public hasTextFocus(): boolean {
return this._hasTextFocus;
}
//#endregion
//#region Testing utils
@@ -79,6 +88,11 @@ export interface TestCodeEditorCreationOptions extends editorOptions.IEditorOpti
*/
model?: ITextModel;
serviceCollection?: ServiceCollection;
/**
* If the editor has text focus.
* Defaults to true.
*/
hasTextFocus?: boolean;
}
export function withTestCodeEditor(text: string | string[] | null, options: TestCodeEditorCreationOptions, callback: (editor: ITestCodeEditor, viewModel: ViewModel) => void): void {
@@ -99,7 +113,7 @@ export function withTestCodeEditor(text: string | string[] | null, options: Test
editor.dispose();
}
export async function withAsyncTestCodeEditor(text: string | string[] | null, options: TestCodeEditorCreationOptions, callback: (editor: ITestCodeEditor, viewModel: ViewModel) => Promise<void>): Promise<void> {
export async function withAsyncTestCodeEditor(text: string | string[] | null, options: TestCodeEditorCreationOptions, callback: (editor: ITestCodeEditor, viewModel: ViewModel, instantiationService: IInstantiationService) => Promise<void>): Promise<void> {
// create a model if necessary and remember it in order to dispose it.
if (!options.model) {
if (typeof text === 'string') {
@@ -109,15 +123,20 @@ export async function withAsyncTestCodeEditor(text: string | string[] | null, op
}
}
const editor = createTestCodeEditor(options);
const [instantiationService, editor] = doCreateTestCodeEditor(options);
const viewModel = editor.getViewModel()!;
viewModel.setHasFocus(true);
await callback(<ITestCodeEditor>editor, editor.getViewModel()!);
await callback(<ITestCodeEditor>editor, editor.getViewModel()!, instantiationService);
editor.dispose();
}
export function createTestCodeEditor(options: TestCodeEditorCreationOptions): ITestCodeEditor {
const [, editor] = doCreateTestCodeEditor(options);
return editor;
}
function doCreateTestCodeEditor(options: TestCodeEditorCreationOptions): [IInstantiationService, ITestCodeEditor] {
const model = options.model;
delete options.model;
@@ -142,6 +161,9 @@ export function createTestCodeEditor(options: TestCodeEditorCreationOptions): IT
if (!services.has(IThemeService)) {
services.set(IThemeService, new TestThemeService());
}
if (!services.has(ITelemetryService)) {
services.set(ITelemetryService, NullTelemetryService);
}
const codeEditorWidgetOptions: ICodeEditorWidgetOptions = {
contributions: []
@@ -152,6 +174,10 @@ export function createTestCodeEditor(options: TestCodeEditorCreationOptions): IT
options,
codeEditorWidgetOptions
);
if (typeof options.hasTextFocus === 'undefined') {
options.hasTextFocus = true;
}
editor.setHasTextFocus(options.hasTextFocus);
editor.setModel(model);
return <ITestCodeEditor>editor;
return [instantiationService, <ITestCodeEditor>editor];
}

View File

@@ -26,7 +26,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
import { INotebookSearchOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { EditorStartFindAction, EditorStartFindReplaceAction } from 'vs/editor/contrib/find/findController';
import { StartFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/findController';
const FIND_HIDE_TRANSITION = 'find-hide-transition';
const FIND_SHOW_TRANSITION = 'find-show-transition';
@@ -404,7 +404,7 @@ registerAction2(class extends Action2 {
}
});
EditorStartFindAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => {
StartFindAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => {
const editorService = accessor.get(IEditorService);
const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
@@ -417,7 +417,7 @@ EditorStartFindAction.addImplementation(100, (accessor: ServicesAccessor, args:
return true;
});
EditorStartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => {
StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => {
const editorService = accessor.get(IEditorService);
const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);

View File

@@ -40,6 +40,7 @@ suite('MainThreadDocumentsAndEditors', () => {
function myCreateTestCodeEditor(model: ITextModel | undefined): ITestCodeEditor {
return createTestCodeEditor({
model: model,
hasTextFocus: false,
serviceCollection: new ServiceCollection(
[ICodeEditorService, codeEditorService]
)