Editors: revisit need for populateEditorId and doResolveEditor (#127787)

* extract `editorGroupFinder` to its own type

* Adopt new findGroup

* Address PR feedback

* make preferred group reusable

* 💄

Co-authored-by: Logan Ramos <lramos15@gmail.com>
This commit is contained in:
Benjamin Pasero 2021-07-07 11:38:03 +02:00 committed by GitHub
parent c9aea49a87
commit 4fbcc9c3a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 300 additions and 276 deletions

View file

@ -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.

View file

@ -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) {

View file

@ -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<boolean>('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;
}

View file

@ -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<ReturnedOverride> {
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<ReturnedOverride> {
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;
}

View file

@ -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<IEditorPane | undefined>;
openEditor(editor: IUntypedEditorInput, group?: OpenInEditorGroup): Promise<IEditorPane | undefined>;
openEditor(editor: IResourceEditorInput, group?: OpenInEditorGroup): Promise<IEditorPane | undefined>;
openEditor(editor: ITextResourceEditorInput | IUntitledTextResourceEditorInput, group?: OpenInEditorGroup): Promise<ITextEditorPane | undefined>;
openEditor(editor: IResourceDiffEditorInput, group?: OpenInEditorGroup): Promise<ITextDiffEditorPane | undefined>;
async openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | OpenInEditorGroup, preferredGroup?: OpenInEditorGroup): Promise<IEditorPane | undefined> {
openEditor(editor: IEditorInput, options?: IEditorOptions, group?: PreferredGroup): Promise<IEditorPane | undefined>;
openEditor(editor: IUntypedEditorInput, options?: IEditorOptions, group?: PreferredGroup): Promise<IEditorPane | undefined>;
openEditor(editor: IResourceEditorInput, group?: PreferredGroup): Promise<IEditorPane | undefined>;
openEditor(editor: ITextResourceEditorInput | IUntitledTextResourceEditorInput, group?: PreferredGroup): Promise<ITextEditorPane | undefined>;
openEditor(editor: IResourceDiffEditorInput, group?: PreferredGroup): Promise<ITextDiffEditorPane | undefined>;
openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | PreferredGroup, preferredGroup?: PreferredGroup): Promise<IEditorPane | undefined>;
async openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | PreferredGroup, preferredGroup?: PreferredGroup): Promise<IEditorPane | undefined> {
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<boolean>('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<IEditorPane[]>;
openEditors(editors: IUntypedEditorInput[], group?: OpenInEditorGroup, options?: IOpenEditorsOptions): Promise<IEditorPane[]>;
openEditors(editors: Array<IEditorInputWithOptions | IUntypedEditorInput>, group?: OpenInEditorGroup, options?: IOpenEditorsOptions): Promise<IEditorPane[]>;
async openEditors(editors: Array<IEditorInputWithOptions | IUntypedEditorInput>, preferredGroup?: OpenInEditorGroup, options?: IOpenEditorsOptions): Promise<IEditorPane[]> {
openEditors(editors: IEditorInputWithOptions[], group?: PreferredGroup, options?: IOpenEditorsOptions): Promise<IEditorPane[]>;
openEditors(editors: IUntypedEditorInput[], group?: PreferredGroup, options?: IOpenEditorsOptions): Promise<IEditorPane[]>;
openEditors(editors: Array<IEditorInputWithOptions | IUntypedEditorInput>, group?: PreferredGroup, options?: IOpenEditorsOptions): Promise<IEditorPane[]>;
async openEditors(editors: Array<IEditorInputWithOptions | IUntypedEditorInput>, preferredGroup?: PreferredGroup, options?: IOpenEditorsOptions): Promise<IEditorPane[]> {
// 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,

View file

@ -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<IEditorOverrideService>('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<ReturnedOverride>;
resolveEditor(editor: IEditorInputWithOptions | IUntypedEditorInput, preferredGroup: PreferredGroup | undefined): Promise<ReturnedOverride>;
/**
* Given a resource returns all the editor ids that match that resource

View file

@ -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<IEditorService>('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 {
/**

View file

@ -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) {

View file

@ -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<IEditorPane | undefined> {
async function openEditor(editor: IEditorInputWithOptions | IUntypedEditorInput, group?: PreferredGroup): Promise<IEditorPane | undefined> {
if (useOpenEditors) {
const panes = await service.openEditors([editor], group);

View file

@ -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'));
});

View file

@ -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<IEditorPane | undefined>;
openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<ITextEditorPane | undefined>;
openEditor(editor: IResourceDiffEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<ITextDiffEditorPane | undefined>;
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<IEditorPane | undefined> {
openEditor(editor: IEditorInput, options?: IEditorOptions, group?: PreferredGroup): Promise<IEditorPane | undefined>;
openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: PreferredGroup): Promise<ITextEditorPane | undefined>;
openEditor(editor: IResourceDiffEditorInput, group?: PreferredGroup): Promise<ITextDiffEditorPane | undefined>;
async openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrGroup?: IEditorOptions | PreferredGroup, group?: PreferredGroup): Promise<IEditorPane | undefined> {
throw new Error('not implemented');
}
doResolveEditorOpenRequest(editor: IEditorInput | IUntypedEditorInput): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined {