diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 26b58c90fd4..e70ea295e72 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -756,12 +756,22 @@ export interface IEditorInputWithOptions { options?: IEditorOptions; } +export interface IEditorInputWithOptionsAndGroup extends IEditorInputWithOptions { + group: IEditorGroup; +} + export function isEditorInputWithOptions(editor: unknown): editor is IEditorInputWithOptions { const candidate = editor as IEditorInputWithOptions | undefined; return isEditorInput(candidate?.editor); } +export function isEditorInputWithOptionsAndGroup(editor: unknown): editor is IEditorInputWithOptionsAndGroup { + const candidate = editor as IEditorInputWithOptionsAndGroup | undefined; + + return isEditorInputWithOptions(editor) && candidate?.group !== undefined; +} + /** * Context passed into `EditorPane#setInput` to give additional * context information around why the editor was opened. diff --git a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts index 14809e2ccd0..a244e0a8939 100644 --- a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts @@ -55,7 +55,7 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor { input.setForceOpenAsText(); // Try to let the user pick an override if there is one availabe - let overridenInput: ReturnedOverride | undefined = await this.editorOverrideService.resolveEditorInput({ resource: editor.resource, options: { ...options, override: EditorOverride.PICK } }, this.group); + let overridenInput: ReturnedOverride | undefined = await this.editorOverrideService.resolveEditor({ resource: editor.resource, options: { ...options, override: EditorOverride.PICK } }, this.group); if (overridenInput === OverrideStatus.NONE) { overridenInput = undefined; } else if (overridenInput === OverrideStatus.ABORT) { diff --git a/src/vs/workbench/services/editor/browser/editorGroupFinder.ts b/src/vs/workbench/services/editor/browser/editorGroupFinder.ts new file mode 100644 index 00000000000..f59700dcfd6 --- /dev/null +++ b/src/vs/workbench/services/editor/browser/editorGroupFinder.ts @@ -0,0 +1,131 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { EditorActivation } from 'vs/platform/editor/common/editor'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IEditorInputWithOptions, isEditorInputWithOptions, IUntypedEditorInput } from 'vs/workbench/common/editor'; +import { IEditorGroup, GroupsOrder, preferredSideBySideGroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { PreferredGroup, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; + +/** + * Finds the target `IEditorGroup` given the instructions provided + * that is best for the editor and matches the preferred group if + * posisble. + */ +export function findGroup(accessor: ServicesAccessor, editor: IUntypedEditorInput, preferredGroup: PreferredGroup | undefined): [IEditorGroup, EditorActivation | undefined]; +export function findGroup(accessor: ServicesAccessor, editor: IEditorInputWithOptions, preferredGroup: PreferredGroup | undefined): [IEditorGroup, EditorActivation | undefined]; +export function findGroup(accessor: ServicesAccessor, editor: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: PreferredGroup | undefined): [IEditorGroup, EditorActivation | undefined]; +export function findGroup(accessor: ServicesAccessor, editor: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: PreferredGroup | undefined): [IEditorGroup, EditorActivation | undefined] { + const editorGroupService = accessor.get(IEditorGroupsService); + const configurationService = accessor.get(IConfigurationService); + + const group = doFindGroup(editor, preferredGroup, editorGroupService, configurationService); + + // Resolve editor activation strategy + let activation: EditorActivation | undefined = undefined; + if ( + editorGroupService.activeGroup !== group && // only if target group is not already active + editor.options && !editor.options.inactive && // never for inactive editors + editor.options.preserveFocus && // only if preserveFocus + typeof editor.options.activation !== 'number' && // only if activation is not already defined (either true or false) + preferredGroup !== SIDE_GROUP // never for the SIDE_GROUP + ) { + // If the resolved group is not the active one, we typically + // want the group to become active. There are a few cases + // where we stay away from encorcing this, e.g. if the caller + // is already providing `activation`. + // + // Specifically for historic reasons we do not activate a + // group is it is opened as `SIDE_GROUP` with `preserveFocus:true`. + // repeated Alt-clicking of files in the explorer always open + // into the same side group and not cause a group to be created each time. + activation = EditorActivation.ACTIVATE; + } + + return [group, activation]; +} + +function doFindGroup(input: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: PreferredGroup | undefined, editorGroupService: IEditorGroupsService, configurationService: IConfigurationService): IEditorGroup { + let group: IEditorGroup | undefined; + let editor = isEditorInputWithOptions(input) ? input.editor : input; + let options = input.options; + + // Group: Instance of Group + if (preferredGroup && typeof preferredGroup !== 'number') { + group = preferredGroup; + } + + // Group: Side by Side + else if (preferredGroup === SIDE_GROUP) { + group = doFindSideBySideGroup(editorGroupService, configurationService); + } + + // Group: Specific Group + else if (typeof preferredGroup === 'number' && preferredGroup >= 0) { + group = editorGroupService.getGroup(preferredGroup); + } + + // Group: Unspecified without a specific index to open + else if (!options || typeof options.index !== 'number') { + const groupsByLastActive = editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); + + // Respect option to reveal an editor if it is already visible in any group + if (options?.revealIfVisible) { + for (const lastActiveGroup of groupsByLastActive) { + if (lastActiveGroup.isActive(editor)) { + group = lastActiveGroup; + break; + } + } + } + + // Respect option to reveal an editor if it is open (not necessarily visible) + // Still prefer to reveal an editor in a group where the editor is active though. + if (!group) { + if (options?.revealIfOpened || configurationService.getValue('workbench.editor.revealIfOpen')) { + let groupWithInputActive: IEditorGroup | undefined = undefined; + let groupWithInputOpened: IEditorGroup | undefined = undefined; + + for (const group of groupsByLastActive) { + if (group.contains(editor)) { + if (!groupWithInputOpened) { + groupWithInputOpened = group; + } + + if (!groupWithInputActive && group.isActive(editor)) { + groupWithInputActive = group; + } + } + + if (groupWithInputOpened && groupWithInputActive) { + break; // we found all groups we wanted + } + } + + // Prefer a target group where the input is visible + group = groupWithInputActive || groupWithInputOpened; + } + } + } + + // Fallback to active group if target not valid + if (!group) { + group = editorGroupService.activeGroup; + } + + return group; +} + +function doFindSideBySideGroup(editorGroupService: IEditorGroupsService, configurationService: IConfigurationService): IEditorGroup { + const direction = preferredSideBySideGroupDirection(configurationService); + + let neighbourGroup = editorGroupService.findGroup({ direction }); + if (!neighbourGroup) { + neighbourGroup = editorGroupService.addGroup(editorGroupService.activeGroup, direction); + } + + return neighbourGroup; +} diff --git a/src/vs/workbench/services/editor/browser/editorOverrideService.ts b/src/vs/workbench/services/editor/browser/editorOverrideService.ts index 2da64bab8a7..cecc9f2c41c 100644 --- a/src/vs/workbench/services/editor/browser/editorOverrideService.ts +++ b/src/vs/workbench/services/editor/browser/editorOverrideService.ts @@ -10,7 +10,7 @@ import { basename, extname, isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { EditorActivation, EditorOverride, IEditorOptions } from 'vs/platform/editor/common/editor'; -import { DEFAULT_EDITOR_ASSOCIATION, EditorResourceAccessor, IEditorInput, IEditorInputWithOptions, isResourceDiffEditorInput, isUntitledResourceEditorInput, IUntypedEditorInput, SideBySideEditor } from 'vs/workbench/common/editor'; +import { DEFAULT_EDITOR_ASSOCIATION, EditorResourceAccessor, IEditorInput, IEditorInputWithOptions, isEditorInputWithOptions, isResourceDiffEditorInput, isUntitledResourceEditorInput, IUntypedEditorInput, SideBySideEditor, UntypedEditorContext } from 'vs/workbench/common/editor'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { Schemas } from 'vs/base/common/network'; import { RegisteredEditorInfo, RegisteredEditorPriority, RegisteredEditorOptions, DiffEditorInputFactoryFunction, EditorAssociation, EditorAssociations, EditorInputFactoryFunction, editorsAssociationsSettingId, globMatchesResource, IEditorOverrideService, priorityToRank, ReturnedOverride, OverrideStatus, UntitledEditorInputFactoryFunction } from 'vs/workbench/services/editor/common/editorOverrideService'; @@ -22,6 +22,9 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { ILogService } from 'vs/platform/log/common/log'; +import { findGroup } from 'vs/workbench/services/editor/browser/editorGroupFinder'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { PreferredGroup } from 'vs/workbench/services/editor/common/editorService'; interface RegisteredEditor { globPattern: string | glob.IRelativePattern, @@ -48,6 +51,7 @@ export class EditorOverrideService extends Disposable implements IEditorOverride constructor( @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, + @IInstantiationService private readonly instantiationService: IInstantiationService, @IConfigurationService private readonly configurationService: IConfigurationService, @IQuickInputService private readonly quickInputService: IQuickInputService, @INotificationService private readonly notificationService: INotificationService, @@ -80,8 +84,50 @@ export class EditorOverrideService extends Disposable implements IEditorOverride })); } - async populateEditorId(editor: IUntypedEditorInput): Promise<{ conflictingDefault: boolean } | undefined> { - let resource = EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }); + private async resolveUntypedInputAndGroup(editor: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: PreferredGroup | undefined): Promise<[IUntypedEditorInput, IEditorGroup, EditorActivation | undefined] | undefined> { + let untypedEditor: IUntypedEditorInput | undefined = undefined; + + // Typed: convert to untyped to be able to resolve the override + if (isEditorInputWithOptions(editor)) { + untypedEditor = editor.editor.toUntyped(undefined, UntypedEditorContext.Default); + + if (untypedEditor) { + // Preserve original options: specifically it is + // possible that a `override` was defined from + // the outside and we do not want to loose it. + untypedEditor.options = { ...untypedEditor.options, ...editor.options }; + } + } + + // Untyped: take as is + else { + untypedEditor = editor; + } + + // Typed editors that cannot convert to untyped will be returned as undefined + if (!untypedEditor) { + return undefined; + } + // Use the untyped editor to find a group + const [group, activation] = this.instantiationService.invokeFunction(findGroup, untypedEditor, preferredGroup); + + return [untypedEditor, group, activation]; + } + + async resolveEditor(editor: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: PreferredGroup | undefined): Promise { + const resolvedUntypedAndGroup = await this.resolveUntypedInputAndGroup(editor, preferredGroup); + if (!resolvedUntypedAndGroup) { + return OverrideStatus.NONE; + } + // Get the resolved untyped editor, group, and activation + const [untypedEditor, group, activation] = resolvedUntypedAndGroup; + if (activation) { + untypedEditor.options = { ...untypedEditor.options, activation }; + } + + let resource = EditorResourceAccessor.getCanonicalUri(untypedEditor, { supportSideBySide: SideBySideEditor.PRIMARY }); + let options = untypedEditor.options; + // If it was an override before we await for the extensions to activate and then proceed with overriding or else they won't be registered if (this.cache && resource && this.resourceMatchesCache(resource)) { await this.extensionService.whenInstalledExtensionsRegistered(); @@ -91,47 +137,28 @@ export class EditorOverrideService extends Disposable implements IEditorOverride resource = URI.from({ scheme: Schemas.untitled }); } - if (editor.options?.override === EditorOverride.DISABLED) { + if (untypedEditor.options?.override === EditorOverride.DISABLED) { throw new Error(`Calling resolve editor override when override is explicitly disabled!`); } - if (editor.options?.override === EditorOverride.PICK) { - const picked = await this.doPickEditorOverride(editor); + if (untypedEditor.options?.override === EditorOverride.PICK) { + const picked = await this.doPickEditorOverride(untypedEditor); // If the picker was cancelled we will stop resolving the override if (!picked) { - return undefined; + return OverrideStatus.ABORT; } // Populate the options with the new ones - editor.options = picked; - return { conflictingDefault: false }; - } - - const { editor: selectedEditor, conflictingDefault } = this.getEditor(resource, editor.options?.override); - editor.options = { ...editor.options, override: selectedEditor?.editorInfo.id }; - return { conflictingDefault }; - } - - async resolveEditorInput(editor: IUntypedEditorInput, group: IEditorGroup, conflictingDefault?: boolean): Promise { - let resource = EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }); - let options = editor.options; - - - if (resource === undefined) { - resource = URI.from({ scheme: Schemas.untitled }); - } - - if (!options?.override || typeof options.override !== 'string') { - await this.populateEditorId(editor); + untypedEditor.options = picked; } // Resolved the override as much as possible, now find a given editor (cast here is ok because we resolve down to a string above) - const { editor: selectedEditor } = this.getEditor(resource, editor.options?.override as string | undefined); + const { editor: selectedEditor, conflictingDefault } = this.getEditor(resource, untypedEditor.options?.override as (string | EditorOverride.EXCLUSIVE_ONLY | undefined)); if (!selectedEditor) { return OverrideStatus.NONE; } const handlesDiff = typeof selectedEditor.options?.canHandleDiff === 'function' ? selectedEditor.options.canHandleDiff() : selectedEditor.options?.canHandleDiff; - if (handlesDiff === false && isResourceDiffEditorInput(editor)) { + if (handlesDiff === false && isResourceDiffEditorInput(untypedEditor)) { return OverrideStatus.NONE; } @@ -139,17 +166,17 @@ export class EditorOverrideService extends Disposable implements IEditorOverride const activeEditor = group.activeEditor; const isActive = activeEditor ? activeEditor.editorId === selectedEditor.editorInfo.id && isEqual(activeEditor.resource, resource) : false; if (activeEditor && isActive) { - return { editor: activeEditor, options }; + return { editor: activeEditor, options, group }; } - const input = await this.doOverrideEditorInput(editor, group, selectedEditor); + const input = await this.doOverrideEditorInput(untypedEditor, group, selectedEditor); if (conflictingDefault && input) { // Show the conflicting default dialog - await this.doHandleConflictingDefaults(resource, selectedEditor.editorInfo.label, editor, input.editor, group); + await this.doHandleConflictingDefaults(resource, selectedEditor.editorInfo.label, untypedEditor, input.editor, group); } if (input) { this.sendOverrideTelemetry(input.editor); - return input; + return { ...input, group }; } return OverrideStatus.ABORT; } @@ -440,7 +467,7 @@ export class EditorOverrideService extends Disposable implements IEditorOverride return; } untypedInput.options = picked; - const replacementEditor = await this.resolveEditorInput(untypedInput, group); + const replacementEditor = await this.resolveEditor(untypedInput, group); if (replacementEditor === OverrideStatus.ABORT || replacementEditor === OverrideStatus.NONE) { return; } diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index fafa037913f..e76183087b7 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -5,7 +5,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IResourceEditorInput, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier, ITextEditorOptions, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; -import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, EditorInputCapabilities, isResourceDiffEditorInput, IUntypedEditorInput, DEFAULT_EDITOR_ASSOCIATION, UntypedEditorContext, isResourceEditorInput, isEditorInput } from 'vs/workbench/common/editor'; +import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, EditorInputCapabilities, isResourceDiffEditorInput, IUntypedEditorInput, DEFAULT_EDITOR_ASSOCIATION, isResourceEditorInput, isEditorInput, isEditorInputWithOptionsAndGroup } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; @@ -18,8 +18,8 @@ import { Event, Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; import { basename, joinPath } from 'vs/base/common/resources'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; -import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, GroupChangeKind, preferredSideBySideGroupDirection, isEditorReplacement, isEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { SIDE_GROUP, IUntypedEditorReplacement, IEditorService, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE, ISaveEditorsOptions, ISaveAllEditorsOptions, IRevertAllEditorsOptions, IBaseSaveRevertAllEditorOptions, IOpenEditorsOptions } from 'vs/workbench/services/editor/common/editorService'; +import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, GroupChangeKind, isEditorReplacement } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IUntypedEditorReplacement, IEditorService, ISaveEditorsOptions, ISaveAllEditorsOptions, IRevertAllEditorsOptions, IBaseSaveRevertAllEditorOptions, IOpenEditorsOptions, PreferredGroup, isPreferredGroup } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { Disposable, IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle'; import { coalesce, distinct } from 'vs/base/common/arrays'; @@ -34,19 +34,13 @@ import { Promises, timeout } from 'vs/base/common/async'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { indexOfPath } from 'vs/base/common/extpath'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; -import { RegisteredEditorPriority, IEditorOverrideService, OverrideStatus, ReturnedOverride } from 'vs/workbench/services/editor/common/editorOverrideService'; +import { RegisteredEditorPriority, IEditorOverrideService, OverrideStatus } from 'vs/workbench/services/editor/common/editorOverrideService'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkspaceTrustRequestService, WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust'; import { IHostService } from 'vs/workbench/services/host/browser/host'; +import { findGroup } from 'vs/workbench/services/editor/browser/editorGroupFinder'; type CachedEditorInput = TextResourceEditorInput | IFileEditorInput | UntitledTextEditorInput; -type OpenInEditorGroup = IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE; - -function isOpenInEditorGroup(obj: unknown): obj is OpenInEditorGroup { - const candidate = obj as OpenInEditorGroup | undefined; - - return typeof obj === 'number' || isEditorGroup(candidate); -} export class EditorService extends Disposable implements EditorServiceImpl { @@ -514,36 +508,34 @@ export class EditorService extends Disposable implements EditorServiceImpl { //#region openEditor() - openEditor(editor: IEditorInput, options?: IEditorOptions, group?: OpenInEditorGroup): Promise; - openEditor(editor: IUntypedEditorInput, group?: OpenInEditorGroup): Promise; - openEditor(editor: IResourceEditorInput, group?: OpenInEditorGroup): Promise; - openEditor(editor: ITextResourceEditorInput | IUntitledTextResourceEditorInput, group?: OpenInEditorGroup): Promise; - openEditor(editor: IResourceDiffEditorInput, group?: OpenInEditorGroup): Promise; - async openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | OpenInEditorGroup, preferredGroup?: OpenInEditorGroup): Promise { + openEditor(editor: IEditorInput, options?: IEditorOptions, group?: PreferredGroup): Promise; + openEditor(editor: IUntypedEditorInput, options?: IEditorOptions, group?: PreferredGroup): Promise; + openEditor(editor: IResourceEditorInput, group?: PreferredGroup): Promise; + openEditor(editor: ITextResourceEditorInput | IUntitledTextResourceEditorInput, group?: PreferredGroup): Promise; + openEditor(editor: IResourceDiffEditorInput, group?: PreferredGroup): Promise; + openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | PreferredGroup, preferredGroup?: PreferredGroup): Promise; + async openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | PreferredGroup, preferredGroup?: PreferredGroup): Promise { let typedEditor: IEditorInput | undefined = undefined; let options = isEditorInput(editor) ? optionsOrPreferredGroup as IEditorOptions : editor.options; let group: IEditorGroup | undefined = undefined; - let activation: EditorActivation | undefined = undefined; - if (isOpenInEditorGroup(optionsOrPreferredGroup)) { + if (isPreferredGroup(optionsOrPreferredGroup)) { preferredGroup = optionsOrPreferredGroup; } // Resolve override unless disabled if (options?.override !== EditorOverride.DISABLED) { - const [resolvedEditor, resolvedGroup, resolvedActivation] = await this.doResolveEditor(isEditorInput(editor) ? { editor, options } : editor, preferredGroup); + const resolvedEditor = await this.editorOverrideService.resolveEditor(isEditorInput(editor) ? { editor, options } : editor, preferredGroup); if (resolvedEditor === OverrideStatus.ABORT) { return; // skip editor if override is aborted } - group = resolvedGroup; - activation = resolvedActivation; - // We resolved an editor to use - if (isEditorInputWithOptions(resolvedEditor)) { + if (isEditorInputWithOptionsAndGroup(resolvedEditor)) { typedEditor = resolvedEditor.editor; options = resolvedEditor.options; + group = resolvedEditor.group; } } @@ -554,185 +546,26 @@ export class EditorService extends Disposable implements EditorServiceImpl { // If group still isn't defined because of a disabled override we resolve it if (!group) { - ([group, activation] = this.findTargetGroup({ editor: typedEditor, options }, preferredGroup)); - } + let activation: EditorActivation | undefined = undefined; + ([group, activation] = this.instantiationService.invokeFunction(findGroup, { editor: typedEditor, options }, preferredGroup)); - // Mixin editor group activation if any - if (activation) { - options = { ...options, activation }; + // Mixin editor group activation if returned + if (activation) { + options = { ...options, activation }; + } } return group.openEditor(typedEditor, options); } - private async doResolveEditor(editor: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: OpenInEditorGroup | undefined): Promise<[ReturnedOverride, IEditorGroup | undefined, EditorActivation | undefined]> { - let untypedEditor: IUntypedEditorInput | undefined = undefined; - - // Typed: convert to untyped to be able to resolve the override - if (isEditorInputWithOptions(editor)) { - untypedEditor = editor.editor.toUntyped(undefined, UntypedEditorContext.Default); - - if (untypedEditor) { - // Preserve original options: specifically it is - // possible that a `override` was defined from - // the outside and we do not want to loose it. - untypedEditor.options = { ...untypedEditor.options, ...editor.options }; - } - } - - // Untyped: take as is - else { - untypedEditor = editor; - } - - // Typed editors that cannot convert to untyped will be taken - // as is without override. - if (!untypedEditor) { - return [OverrideStatus.NONE, undefined, undefined]; - } - - // We need a `override` for the untyped editor if it is - // not there so we call into the editor override service - let hasConflictingDefaults = false; - if (typeof untypedEditor.options?.override !== 'string') { - const populatedInfo = await this.editorOverrideService.populateEditorId(untypedEditor); - if (!populatedInfo) { - return [OverrideStatus.ABORT, undefined, undefined]; // we could not resolve the editor id - } - - hasConflictingDefaults = populatedInfo.conflictingDefault; - } - - // If we didn't get an override just return as none and let the editor continue as normal - if (!untypedEditor.options?.override) { - return [OverrideStatus.NONE, undefined, undefined]; - } - - // Find the target group for the editor - const [group, activation] = this.findTargetGroup(untypedEditor, preferredGroup); - - return [await this.editorOverrideService.resolveEditorInput(untypedEditor, group, hasConflictingDefaults), group, activation]; - } - - private findTargetGroup(editor: IEditorInputWithOptions, preferredGroup: OpenInEditorGroup | undefined): [IEditorGroup, EditorActivation | undefined]; - private findTargetGroup(editor: IUntypedEditorInput, preferredGroup: OpenInEditorGroup | undefined): [IEditorGroup, EditorActivation | undefined]; - private findTargetGroup(editor: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: OpenInEditorGroup | undefined): [IEditorGroup, EditorActivation | undefined] { - const group = this.doFindTargetGroup(editor, preferredGroup); - - // Resolve editor activation strategy - let activation: EditorActivation | undefined = undefined; - if ( - this.editorGroupService.activeGroup !== group && // only if target group is not already active - editor.options && !editor.options.inactive && // never for inactive editors - editor.options.preserveFocus && // only if preserveFocus - typeof editor.options.activation !== 'number' && // only if activation is not already defined (either true or false) - preferredGroup !== SIDE_GROUP // never for the SIDE_GROUP - ) { - // If the resolved group is not the active one, we typically - // want the group to become active. There are a few cases - // where we stay away from encorcing this, e.g. if the caller - // is already providing `activation`. - // - // Specifically for historic reasons we do not activate a - // group is it is opened as `SIDE_GROUP` with `preserveFocus:true`. - // repeated Alt-clicking of files in the explorer always open - // into the same side group and not cause a group to be created each time. - activation = EditorActivation.ACTIVATE; - } - - return [group, activation]; - } - - private doFindTargetGroup(input: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: OpenInEditorGroup | undefined): IEditorGroup { - let group: IEditorGroup | undefined; - let editor = isEditorInputWithOptions(input) ? input.editor : input; - let options = input.options; - - // Group: Instance of Group - if (preferredGroup && typeof preferredGroup !== 'number') { - group = preferredGroup; - } - - // Group: Side by Side - else if (preferredGroup === SIDE_GROUP) { - group = this.findSideBySideGroup(); - } - - // Group: Specific Group - else if (typeof preferredGroup === 'number' && preferredGroup >= 0) { - group = this.editorGroupService.getGroup(preferredGroup); - } - - // Group: Unspecified without a specific index to open - else if (!options || typeof options.index !== 'number') { - const groupsByLastActive = this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); - - // Respect option to reveal an editor if it is already visible in any group - if (options?.revealIfVisible) { - for (const lastActiveGroup of groupsByLastActive) { - if (lastActiveGroup.isActive(editor)) { - group = lastActiveGroup; - break; - } - } - } - - // Respect option to reveal an editor if it is open (not necessarily visible) - // Still prefer to reveal an editor in a group where the editor is active though. - if (!group) { - if (options?.revealIfOpened || this.configurationService.getValue('workbench.editor.revealIfOpen')) { - let groupWithInputActive: IEditorGroup | undefined = undefined; - let groupWithInputOpened: IEditorGroup | undefined = undefined; - - for (const group of groupsByLastActive) { - if (group.contains(editor)) { - if (!groupWithInputOpened) { - groupWithInputOpened = group; - } - - if (!groupWithInputActive && group.isActive(editor)) { - groupWithInputActive = group; - } - } - - if (groupWithInputOpened && groupWithInputActive) { - break; // we found all groups we wanted - } - } - - // Prefer a target group where the input is visible - group = groupWithInputActive || groupWithInputOpened; - } - } - } - - // Fallback to active group if target not valid - if (!group) { - group = this.editorGroupService.activeGroup; - } - - return group; - } - - private findSideBySideGroup(): IEditorGroup { - const direction = preferredSideBySideGroupDirection(this.configurationService); - - let neighbourGroup = this.editorGroupService.findGroup({ direction }); - if (!neighbourGroup) { - neighbourGroup = this.editorGroupService.addGroup(this.editorGroupService.activeGroup, direction); - } - - return neighbourGroup; - } - //#endregion //#region openEditors() - openEditors(editors: IEditorInputWithOptions[], group?: OpenInEditorGroup, options?: IOpenEditorsOptions): Promise; - openEditors(editors: IUntypedEditorInput[], group?: OpenInEditorGroup, options?: IOpenEditorsOptions): Promise; - openEditors(editors: Array, group?: OpenInEditorGroup, options?: IOpenEditorsOptions): Promise; - async openEditors(editors: Array, preferredGroup?: OpenInEditorGroup, options?: IOpenEditorsOptions): Promise { + openEditors(editors: IEditorInputWithOptions[], group?: PreferredGroup, options?: IOpenEditorsOptions): Promise; + openEditors(editors: IUntypedEditorInput[], group?: PreferredGroup, options?: IOpenEditorsOptions): Promise; + openEditors(editors: Array, group?: PreferredGroup, options?: IOpenEditorsOptions): Promise; + async openEditors(editors: Array, preferredGroup?: PreferredGroup, options?: IOpenEditorsOptions): Promise { // Pass all editors to trust service to determine if // we should proceed with opening the editors if we @@ -752,17 +585,16 @@ export class EditorService extends Disposable implements EditorServiceImpl { // Resolve override unless disabled if (editor.options?.override !== EditorOverride.DISABLED) { - const [resolvedEditor, resolvedGroup] = await this.doResolveEditor(editor, preferredGroup); + const resolvedEditor = await this.editorOverrideService.resolveEditor(editor, preferredGroup); if (resolvedEditor === OverrideStatus.ABORT) { continue; // skip editor if override is aborted } - group = resolvedGroup; - // We resolved an editor to use - if (isEditorInputWithOptions(resolvedEditor)) { + if (isEditorInputWithOptionsAndGroup(resolvedEditor)) { typedEditor = resolvedEditor; + group = resolvedEditor.group; } } @@ -773,7 +605,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { // If group still isn't defined because of a disabled override we resolve it if (!group) { - group = this.doFindTargetGroup(typedEditor, preferredGroup); + [group] = this.instantiationService.invokeFunction(findGroup, typedEditor, preferredGroup); } // Update map of groups to editors @@ -991,7 +823,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { // Resolve override unless disabled if (override !== EditorOverride.DISABLED) { - const [resolvedEditor] = await this.doResolveEditor( + const resolvedEditor = await this.editorOverrideService.resolveEditor( isEditorReplacement(replacement) ? { editor: replacement.replacement, options: replacement.options } : replacement.replacement, targetGroup ); @@ -1001,7 +833,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { } // We resolved an editor to use - if (isEditorInputWithOptions(resolvedEditor)) { + if (isEditorInputWithOptionsAndGroup(resolvedEditor)) { typedReplacement = { editor: replacement.editor, replacement: resolvedEditor.editor, diff --git a/src/vs/workbench/services/editor/common/editorOverrideService.ts b/src/vs/workbench/services/editor/common/editorOverrideService.ts index 62f6ee6b38c..0c5b4cd675d 100644 --- a/src/vs/workbench/services/editor/common/editorOverrideService.ts +++ b/src/vs/workbench/services/editor/common/editorOverrideService.ts @@ -15,8 +15,9 @@ import { Extensions as ConfigurationExtensions, IConfigurationNode, IConfigurati import { IResourceEditorInput, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IEditorInputWithOptions, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, IUntypedEditorInput } from 'vs/workbench/common/editor'; +import { IEditorInputWithOptions, IEditorInputWithOptionsAndGroup, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, IUntypedEditorInput } from 'vs/workbench/common/editor'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { PreferredGroup } from 'vs/workbench/services/editor/common/editorService'; export const IEditorOverrideService = createDecorator('editorOverrideService'); @@ -75,7 +76,7 @@ export const enum OverrideStatus { NONE = 2, } -export type ReturnedOverride = IEditorInputWithOptions | OverrideStatus; +export type ReturnedOverride = IEditorInputWithOptionsAndGroup | OverrideStatus; export type RegisteredEditorOptions = { /** @@ -139,22 +140,13 @@ export interface IEditorOverrideService { createDiffEditorInput?: DiffEditorInputFactoryFunction ): IDisposable; - /** - * Populates the override field of the untyped editor input - * @param editor The editor input - * @returns If one is populated whether or not there was a conflicting default, else undefined - */ - populateEditorId(editor: IUntypedEditorInput): Promise<{ conflictingDefault: boolean } | undefined> - /** * Given an editor determines if there's a suitable override for it, if so returns an IEditorInputWithOptions for opening * @param editor The editor to override - * @param options The current options for the editor - * @param group The current group - * @param conflictingDefault Whether or not to show the conflicting default prompt + * @param preferredGroup The group you want to open the editor in * @returns An IEditorInputWithOptionsAndGroup if there is an available override or a status of how to proceed */ - resolveEditorInput(editor: IUntypedEditorInput, group: IEditorGroup, conflictingDefault?: boolean): Promise; + resolveEditor(editor: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: PreferredGroup | undefined): Promise; /** * Given a resource returns all the editor ids that match that resource diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index b93e4031711..d72b6ce9109 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -8,12 +8,40 @@ import { IResourceEditorInput, IEditorOptions, IResourceEditorInputIdentifier, I import { IEditorInput, IEditorPane, GroupIdentifier, IEditorInputWithOptions, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, ITextEditorPane, ITextDiffEditorPane, IEditorIdentifier, ISaveOptions, IRevertOptions, EditorsOrder, IVisibleEditorPane, IEditorCloseEvent, IUntypedEditorInput } from 'vs/workbench/common/editor'; import { Event } from 'vs/base/common/event'; import { IEditor, IDiffEditor } from 'vs/editor/common/editorCommon'; -import { IEditorGroup, IEditorReplacement } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroup, IEditorReplacement, isEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { URI } from 'vs/base/common/uri'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; export const IEditorService = createDecorator('editorService'); +/** + * Open an editor in the currently active group. + */ +export const ACTIVE_GROUP = -1; +export type ACTIVE_GROUP_TYPE = typeof ACTIVE_GROUP; + +/** + * Open an editor to the side of the active group. + */ +export const SIDE_GROUP = -2; +export type SIDE_GROUP_TYPE = typeof SIDE_GROUP; + +export type PreferredGroup = IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE; + +export function isPreferredGroup(obj: unknown): obj is PreferredGroup { + const candidate = obj as PreferredGroup | undefined; + + return typeof obj === 'number' || isEditorGroup(candidate); +} + +export interface ISaveEditorsOptions extends ISaveOptions { + + /** + * If true, will ask for a location of the editor to save to. + */ + readonly saveAs?: boolean; +} + export interface IUntypedEditorReplacement { readonly editor: IEditorInput; readonly replacement: IUntypedEditorInput; @@ -25,20 +53,6 @@ export interface IUntypedEditorReplacement { forceReplaceDirty?: boolean; } -export const ACTIVE_GROUP = -1; -export type ACTIVE_GROUP_TYPE = typeof ACTIVE_GROUP; - -export const SIDE_GROUP = -2; -export type SIDE_GROUP_TYPE = typeof SIDE_GROUP; - -export interface ISaveEditorsOptions extends ISaveOptions { - - /** - * If true, will ask for a location of the editor to save to. - */ - readonly saveAs?: boolean; -} - export interface IBaseSaveRevertAllEditorOptions { /** diff --git a/src/vs/workbench/services/editor/test/browser/editorOverrideService.test.ts b/src/vs/workbench/services/editor/test/browser/editorOverrideService.test.ts index fceaaa9f5f4..6b6d1751f4d 100644 --- a/src/vs/workbench/services/editor/test/browser/editorOverrideService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorOverrideService.test.ts @@ -43,7 +43,7 @@ suite('EditorOverrideService', () => { ({ resource, options }, group) => ({ editor: new TestFileEditorInput(URI.parse(resource.toString()), TEST_EDITOR_INPUT_ID) }), ); - const resultingOverride = await service.resolveEditorInput({ resource: URI.file('my://resource-basics.test') }, part.activeGroup); + const resultingOverride = await service.resolveEditor({ resource: URI.file('my://resource-basics.test') }, part.activeGroup); assert.ok(resultingOverride); assert.notStrictEqual(typeof resultingOverride, 'number'); if (resultingOverride !== OverrideStatus.ABORT && resultingOverride !== OverrideStatus.NONE) { @@ -69,13 +69,13 @@ suite('EditorOverrideService', () => { ); // Untyped untitled - no resource - let resultingOverride = await service.resolveEditorInput({ resource: undefined }, part.activeGroup); + let resultingOverride = await service.resolveEditor({ resource: undefined }, part.activeGroup); assert.ok(resultingOverride); // We don't expect untitled to match the *.test glob assert.strictEqual(typeof resultingOverride, 'number'); // Untyped untitled - with untitled resource - resultingOverride = await service.resolveEditorInput({ resource: URI.from({ scheme: Schemas.untitled, path: 'foo.test' }) }, part.activeGroup); + resultingOverride = await service.resolveEditor({ resource: URI.from({ scheme: Schemas.untitled, path: 'foo.test' }) }, part.activeGroup); assert.ok(resultingOverride); assert.notStrictEqual(typeof resultingOverride, 'number'); if (resultingOverride !== OverrideStatus.ABORT && resultingOverride !== OverrideStatus.NONE) { @@ -84,7 +84,7 @@ suite('EditorOverrideService', () => { } // Untyped untitled - file resource with forceUntitled - resultingOverride = await service.resolveEditorInput({ resource: URI.file('/fake.test'), forceUntitled: true }, part.activeGroup); + resultingOverride = await service.resolveEditor({ resource: URI.file('/fake.test'), forceUntitled: true }, part.activeGroup); assert.ok(resultingOverride); assert.notStrictEqual(typeof resultingOverride, 'number'); if (resultingOverride !== OverrideStatus.ABORT && resultingOverride !== OverrideStatus.NONE) { diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index 87698ed2b5d..5c72f887bec 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -7,13 +7,13 @@ import * as assert from 'assert'; import { EditorActivation, EditorOverride, IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { URI } from 'vs/base/common/uri'; import { Event } from 'vs/base/common/event'; -import { DEFAULT_EDITOR_ASSOCIATION, EditorsOrder, GroupIdentifier, IEditorInputWithOptions, IEditorPane, IResourceDiffEditorInput, isEditorInputWithOptions, isResourceDiffEditorInput, isUntitledResourceEditorInput, IUntitledTextResourceEditorInput, IUntypedEditorInput, UntypedEditorContext } from 'vs/workbench/common/editor'; +import { DEFAULT_EDITOR_ASSOCIATION, EditorsOrder, IEditorInputWithOptions, IEditorPane, IResourceDiffEditorInput, isEditorInputWithOptions, isResourceDiffEditorInput, isUntitledResourceEditorInput, IUntitledTextResourceEditorInput, IUntypedEditorInput, UntypedEditorContext } from 'vs/workbench/common/editor'; import { workbenchInstantiationService, TestServiceAccessor, registerTestEditor, TestFileEditorInput, ITestInstantiationService, registerTestResourceEditor, registerTestSideBySideEditor, createEditorPart, registerTestFileEditor, TestEditorWithOptions, TestTextFileEditor } from 'vs/workbench/test/browser/workbenchTestServices'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { EditorService } from 'vs/workbench/services/editor/browser/editorService'; import { IEditorGroup, IEditorGroupsService, GroupDirection, GroupsArrangement } from 'vs/workbench/services/editor/common/editorGroupsService'; import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; -import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; +import { IEditorService, PreferredGroup, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; @@ -245,7 +245,7 @@ suite('EditorService', () => { rootGroup = part.activeGroup; } - async function openEditor(editor: IEditorInputWithOptions | IUntypedEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise { + async function openEditor(editor: IEditorInputWithOptions | IUntypedEditorInput, group?: PreferredGroup): Promise { if (useOpenEditors) { const panes = await service.openEditors([editor], group); diff --git a/src/vs/workbench/test/browser/parts/editor/editor.test.ts b/src/vs/workbench/test/browser/parts/editor/editor.test.ts index 607fcafee2f..d05634712f1 100644 --- a/src/vs/workbench/test/browser/parts/editor/editor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editor.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, EditorInputCapabilities, isEditorIdentifier, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, isResourceEditorInput, isUntitledResourceEditorInput, isResourceDiffEditorInput } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, EditorInputCapabilities, isEditorIdentifier, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, isResourceEditorInput, isUntitledResourceEditorInput, isResourceDiffEditorInput, isEditorInputWithOptionsAndGroup, IEditorInputWithOptions, isEditorInputWithOptions, isEditorInput, IEditorInputWithOptionsAndGroup } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -331,6 +331,24 @@ suite('Workbench editor utils', () => { assert.strictEqual(isEditorIdentifier({ editor: testInput1, groupId: 3 }), true); }); + test('isEditorInputWithOptionsAndGroup', () => { + const editorInput = new TestFileEditorInput(URI.file('resource1'), 'testTypeId'); + assert.strictEqual(isEditorInput(editorInput), true); + assert.strictEqual(isEditorInputWithOptions(editorInput), false); + assert.strictEqual(isEditorInputWithOptionsAndGroup(editorInput), false); + + const editorInputWithOptions: IEditorInputWithOptions = { editor: editorInput, options: { override: EditorOverride.PICK } }; + assert.strictEqual(isEditorInput(editorInputWithOptions), false); + assert.strictEqual(isEditorInputWithOptions(editorInputWithOptions), true); + assert.strictEqual(isEditorInputWithOptionsAndGroup(editorInputWithOptions), false); + + const service = accessor.editorGroupService; + const editorInputWithOptionsAndGroup: IEditorInputWithOptionsAndGroup = { editor: editorInput, options: { override: EditorOverride.PICK }, group: service.activeGroup }; + assert.strictEqual(isEditorInput(editorInputWithOptionsAndGroup), false); + assert.strictEqual(isEditorInputWithOptions(editorInputWithOptionsAndGroup), true); + assert.strictEqual(isEditorInputWithOptionsAndGroup(editorInputWithOptionsAndGroup), true); + }); + test('whenEditorClosed (single editor)', async function () { return testWhenEditorClosed(false, false, toResource.call(this, '/path/index.txt')); }); diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 449141f125d..4cb6ba51e2a 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -52,7 +52,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IDecorationsService, IResourceDecorationChangeEvent, IDecoration, IDecorationData, IDecorationsProvider } from 'vs/workbench/services/decorations/browser/decorations'; import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IEditorGroupsService, IEditorGroup, GroupsOrder, GroupsArrangement, GroupDirection, IAddGroupOptions, IMergeGroupOptions, IEditorReplacement, IGroupChangeEvent, IFindGroupScope, EditorGroupLayout, ICloseEditorOptions, GroupOrientation, ICloseAllEditorsOptions, ICloseEditorsFilter } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { IEditorService, ISaveEditorsOptions, IRevertAllEditorsOptions, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; +import { IEditorService, ISaveEditorsOptions, IRevertAllEditorsOptions, PreferredGroup } from 'vs/workbench/services/editor/common/editorService'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor'; import { Dimension, IDimension } from 'vs/base/browser/dom'; @@ -813,10 +813,10 @@ export class TestEditorService implements EditorServiceImpl { constructor(private editorGroupService?: IEditorGroupsService) { } getEditors() { return []; } findEditors() { return [] as any; } - openEditor(editor: IEditorInput, options?: IEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceDiffEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - async openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrGroup?: IEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise { + openEditor(editor: IEditorInput, options?: IEditorOptions, group?: PreferredGroup): Promise; + openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: PreferredGroup): Promise; + openEditor(editor: IResourceDiffEditorInput, group?: PreferredGroup): Promise; + async openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrGroup?: IEditorOptions | PreferredGroup, group?: PreferredGroup): Promise { throw new Error('not implemented'); } doResolveEditorOpenRequest(editor: IEditorInput | IUntypedEditorInput): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined {