From 60222b710d4edf766d08fc574165bbfa4f0fab9f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 26 Feb 2021 16:08:41 +0100 Subject: [PATCH] Align `MultiEditorAction` with `MultiCommand` --- src/vs/editor/browser/editorExtensions.ts | 26 ++- src/vs/editor/contrib/find/findController.ts | 181 +++++++++--------- .../contrib/find/test/findController.test.ts | 123 ++++++------ src/vs/editor/test/browser/testCodeEditor.ts | 34 +++- .../browser/contrib/find/findController.ts | 6 +- .../api/mainThreadDocumentsAndEditors.test.ts | 1 + 6 files changed, 195 insertions(+), 176 deletions(-) diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts index 893c2159a8f..b0ff5985cd0 100644 --- a/src/vs/editor/browser/editorExtensions.ts +++ b/src/vs/editor/browser/editorExtensions.ts @@ -339,13 +339,13 @@ export abstract class EditorAction extends EditorCommand { public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise; } -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 { - this.reportTelemetry(accessor, editor); - + public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise { 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; - } //#endregion EditorAction diff --git a/src/vs/editor/contrib/find/findController.ts b/src/vs/editor/contrib/find/findController.ts index 3f2172746ff..8d4e6649a23 100644 --- a/src/vs/editor/contrib/find/findController.ts +++ b/src/vs/editor/contrib/find/findController.ts @@ -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 { - 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 => { + 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 => { + 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 { - 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.get); diff --git a/src/vs/editor/contrib/find/test/findController.test.ts b/src/vs/editor/contrib/find/test/findController.test.ts index 3f55711c155..9daca6b12da 100644 --- a/src/vs/editor/contrib/find/test/findController.test.ts +++ b/src/vs/editor/contrib/find/test/findController.test.ts @@ -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 { + 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, diff --git a/src/vs/editor/test/browser/testCodeEditor.ts b/src/vs/editor/test/browser/testCodeEditor.ts index da4aac2198a..94741e65678 100644 --- a/src/vs/editor/test/browser/testCodeEditor.ts +++ b/src/vs/editor/test/browser/testCodeEditor.ts @@ -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): Promise { +export async function withAsyncTestCodeEditor(text: string | string[] | null, options: TestCodeEditorCreationOptions, callback: (editor: ITestCodeEditor, viewModel: ViewModel, instantiationService: IInstantiationService) => Promise): Promise { // 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(editor, editor.getViewModel()!); + await callback(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 editor; + return [instantiationService, editor]; } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts index da478b8b431..1fcab2227dc 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts @@ -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); diff --git a/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts b/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts index da3e167dfd2..c282692f857 100644 --- a/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts @@ -40,6 +40,7 @@ suite('MainThreadDocumentsAndEditors', () => { function myCreateTestCodeEditor(model: ITextModel | undefined): ITestCodeEditor { return createTestCodeEditor({ model: model, + hasTextFocus: false, serviceCollection: new ServiceCollection( [ICodeEditorService, codeEditorService] )