editors - cleanup editor descriptors and 💄

This commit is contained in:
Benjamin Pasero 2021-05-25 09:33:09 +02:00
parent dee37c6e76
commit 59f5bbaf25
No known key found for this signature in database
GPG key ID: E6380CC4C8219E65
17 changed files with 192 additions and 182 deletions

View file

@ -32,7 +32,9 @@ class MenuActions extends Disposable {
private readonly contextKeyService: IContextKeyService
) {
super();
this.menu = this._register(menuService.createMenu(menuId, contextKeyService));
this._register(this.menu.onDidChange(() => this.updateActions()));
this.updateActions();
}
@ -48,6 +50,7 @@ class MenuActions extends Disposable {
private updateSubmenus(actions: readonly IAction[], submenus: { [id: number]: IMenu }): IDisposable {
const disposables = new DisposableStore();
for (const action of actions) {
if (action instanceof SubmenuItemAction && !submenus[action.item.submenu.id]) {
const menu = submenus[action.item.submenu.id] = disposables.add(this.menuService.createMenu(action.item.submenu, this.contextKeyService));
@ -55,6 +58,7 @@ class MenuActions extends Disposable {
disposables.add(this.updateSubmenus(action.actions, submenus));
}
}
return disposables;
}
}
@ -75,7 +79,9 @@ export class CompositeMenuActions extends Disposable {
@IMenuService private readonly menuService: IMenuService,
) {
super();
this.menuActions = this._register(new MenuActions(menuId, this.options, menuService, contextKeyService));
this._register(this.menuActions.onDidChange(() => this._onDidChange.fire()));
}
@ -89,11 +95,13 @@ export class CompositeMenuActions extends Disposable {
getContextMenuActions(): IAction[] {
const actions: IAction[] = [];
if (this.contextMenuId) {
const menu = this.menuService.createMenu(this.contextMenuId, this.contextKeyService);
this.contextMenuActionsDisposable.value = createAndFillInActionBarActions(menu, this.options, { primary: [], secondary: actions });
menu.dispose();
}
return actions;
}
}

View file

@ -118,10 +118,6 @@ export abstract class Composite extends Component implements IComposite {
this.parent = parent;
}
override updateStyles(): void {
super.updateStyles();
}
/**
* Returns the container this composite is being build in.
*/
@ -158,6 +154,13 @@ export abstract class Composite extends Component implements IComposite {
*/
abstract layout(dimension: Dimension): void;
/**
* Update the styles of the contents of this composite.
*/
override updateStyles(): void {
super.updateStyles();
}
/**
* Returns an array of actions to show in the action bar of the composite.
*/

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { EditorInput, EditorResourceAccessor, IEditorInput, EditorExtensions, SideBySideEditor } from 'vs/workbench/common/editor';
import { EditorInput, EditorResourceAccessor, IEditorInput, EditorExtensions, SideBySideEditor, IEditorDescriptor as ICommonEditorDescriptor } from 'vs/workbench/common/editor';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { Registry } from 'vs/platform/registry/common/platform';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
@ -20,22 +20,7 @@ import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsSe
//#region Editors Registry
export interface IEditorDescriptor {
/**
* The unique identifier of the editor
*/
getId(): string;
/**
* The display name of the editor
*/
getName(): string;
instantiate(instantiationService: IInstantiationService): EditorPane;
describes(obj: unknown): boolean;
}
export interface IEditorDescriptor extends ICommonEditorDescriptor<EditorPane> { }
export interface IEditorRegistry {
@ -48,22 +33,12 @@ export interface IEditorRegistry {
* @param inputDescriptors A set of constructor functions that return an instance of EditorInput for which the
* registered editor should be used for.
*/
registerEditor(descriptor: IEditorDescriptor, inputDescriptors: readonly SyncDescriptor<EditorInput>[]): IDisposable;
registerEditor(editorDescriptor: IEditorDescriptor, inputDescriptors: readonly SyncDescriptor<EditorInput>[]): IDisposable;
/**
* Returns the editor descriptor for the given input or `undefined` if none.
*/
getEditor(input: EditorInput): IEditorDescriptor | undefined;
/**
* Returns the editor descriptor for the given identifier or `undefined` if none.
*/
getEditorById(editorId: string): IEditorDescriptor | undefined;
/**
* Returns an array of registered editors known to the platform.
*/
getEditors(): readonly IEditorDescriptor[];
}
/**
@ -74,36 +49,28 @@ export class EditorDescriptor implements IEditorDescriptor {
static create<Services extends BrandedService[]>(
ctor: { new(...services: Services): EditorPane },
id: string,
typeId: string,
name: string
): EditorDescriptor {
return new EditorDescriptor(ctor as IConstructorSignature0<EditorPane>, id, name);
return new EditorDescriptor(ctor as IConstructorSignature0<EditorPane>, typeId, name);
}
constructor(
private constructor(
private readonly ctor: IConstructorSignature0<EditorPane>,
private readonly id: string,
private readonly name: string
readonly typeId: string,
readonly name: string
) { }
instantiate(instantiationService: IInstantiationService): EditorPane {
return instantiationService.createInstance(this.ctor);
}
getId(): string {
return this.id;
}
getName(): string {
return this.name;
}
describes(obj: unknown): boolean {
return obj instanceof EditorPane && obj.getId() === this.id;
describes(editorPane: EditorPane): boolean {
return editorPane.getId() === this.typeId;
}
}
class EditorRegistry implements IEditorRegistry {
export class EditorRegistry implements IEditorRegistry {
private readonly editors: EditorDescriptor[] = [];
private readonly mapEditorToInputs = new Map<EditorDescriptor, readonly SyncDescriptor<EditorInput>[]>();
@ -120,58 +87,53 @@ class EditorRegistry implements IEditorRegistry {
}
getEditor(input: EditorInput): EditorDescriptor | undefined {
const findEditorDescriptors = (input: EditorInput, byInstanceOf?: boolean): EditorDescriptor[] => {
const matchingDescriptors: EditorDescriptor[] = [];
const descriptors = this.findEditorDescriptors(input);
for (const editor of this.editors) {
const inputDescriptors = this.mapEditorToInputs.get(editor) || [];
for (const inputDescriptor of inputDescriptors) {
const inputClass = inputDescriptor.ctor;
if (descriptors.length === 0) {
return undefined;
}
// Direct check on constructor type (ignores prototype chain)
if (!byInstanceOf && input.constructor === inputClass) {
matchingDescriptors.push(editor);
break;
}
// Normal instanceof check
else if (byInstanceOf && input instanceof inputClass) {
matchingDescriptors.push(editor);
break;
}
}
}
// If no descriptors found, continue search using instanceof and prototype chain
if (!byInstanceOf && matchingDescriptors.length === 0) {
return findEditorDescriptors(input, true);
}
if (byInstanceOf) {
return matchingDescriptors;
}
return matchingDescriptors;
};
const descriptors = findEditorDescriptors(input);
if (descriptors.length > 0) {
// Ask the input for its preferred Editor
const preferredEditorId = input.getPreferredEditorId(descriptors.map(descriptor => descriptor.getId()));
if (preferredEditorId) {
return this.getEditorById(preferredEditorId);
}
// Otherwise, first come first serve
if (descriptors.length === 1) {
return descriptors[0];
}
return undefined;
return input.prefersEditor(descriptors);
}
getEditorById(editorId: string): EditorDescriptor | undefined {
return this.editors.find(editor => editor.getId() === editorId);
private findEditorDescriptors(input: EditorInput, byInstanceOf?: boolean): EditorDescriptor[] {
const matchingDescriptors: EditorDescriptor[] = [];
for (const editor of this.editors) {
const inputDescriptors = this.mapEditorToInputs.get(editor) || [];
for (const inputDescriptor of inputDescriptors) {
const inputClass = inputDescriptor.ctor;
// Direct check on constructor type (ignores prototype chain)
if (!byInstanceOf && input.constructor === inputClass) {
matchingDescriptors.push(editor);
break;
}
// Normal instanceof check
else if (byInstanceOf && input instanceof inputClass) {
matchingDescriptors.push(editor);
break;
}
}
}
// If no descriptors found, continue search using instanceof and prototype chain
if (!byInstanceOf && matchingDescriptors.length === 0) {
return this.findEditorDescriptors(input, true);
}
return matchingDescriptors;
}
//#region Used for tests only
getEditorByType(typeId: string): EditorDescriptor | undefined {
return this.editors.find(editor => editor.typeId === typeId);
}
getEditors(): readonly EditorDescriptor[] {
@ -189,6 +151,8 @@ class EditorRegistry implements IEditorRegistry {
return inputClasses;
}
//#endregion
}
Registry.add(EditorExtensions.Editors, new EditorRegistry());
@ -255,7 +219,6 @@ export function whenEditorClosed(accessor: ServicesAccessor, resources: URI[]):
//#endregion
//#region ARIA
export function computeEditorAriaLabel(input: IEditorInput, index: number | undefined, group: IEditorGroup | undefined, groupCount: number): string {

View file

@ -10,7 +10,7 @@ import { IConstructorSignature0, BrandedService, IInstantiationService } from 'v
import { assertIsDefined } from 'vs/base/common/types';
import { PaneComposite } from 'vs/workbench/browser/panecomposite';
import { IAction, Separator } from 'vs/base/common/actions';
import { CompositeMenuActions } from 'vs/workbench/browser/menuActions';
import { CompositeMenuActions } from 'vs/workbench/browser/actions';
import { MenuId } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IStorageService } from 'vs/platform/storage/common/storage';

View file

@ -143,7 +143,6 @@ export class EditorControl extends Disposable {
if (!editorPane.getContainer()) {
const editorPaneContainer = document.createElement('div');
editorPaneContainer.classList.add('editor-instance');
editorPaneContainer.setAttribute('data-editor-id', descriptor.getId());
editorPane.create(editorPaneContainer);
}

View file

@ -106,7 +106,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan
return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration, {});
}
override async setInput(input: DiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {//
override async setInput(input: DiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
// Dispose previous diff navigator
this.diffNavigatorDisposables.clear();

View file

@ -40,7 +40,7 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { URI } from 'vs/base/common/uri';
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
import { Codicon } from 'vs/base/common/codicons';
import { CompositeMenuActions } from 'vs/workbench/browser/menuActions';
import { CompositeMenuActions } from 'vs/workbench/browser/actions';
export interface IViewPaneOptions extends IPaneOptions {
id: string;

View file

@ -35,7 +35,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
import { CompositeMenuActions } from 'vs/workbench/browser/menuActions';
import { CompositeMenuActions } from 'vs/workbench/browser/actions';
import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { ScrollEvent } from 'vs/base/common/scrollable';

View file

@ -183,7 +183,7 @@ class BrowserMain extends Disposable {
serviceCollection.set(IFileService, fileService);
await this.registerFileSystemProviders(environmentService, fileService, remoteAgentService, logService, logsPath);
// IURIIdentityService
// URI Identity
const uriIdentityService = new UriIdentityService(fileService);
serviceCollection.set(IUriIdentityService, uriIdentityService);

View file

@ -5,7 +5,7 @@
import { setFullscreen } from 'vs/base/browser/browser';
import { addDisposableListener, addDisposableThrottledListener, detectFullscreen, EventHelper, EventType, windowOpenNoOpenerWithSuccess, windowOpenNoOpener } from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
import { DomEmitter } from 'vs/base/browser/event';
import { timeout } from 'vs/base/common/async';
import { Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
@ -89,8 +89,8 @@ export class BrowserWindow extends Disposable {
// when shutdown has happened to not show the dialog e.g.
// when navigation takes a longer time.
Event.toPromise(Event.any(
Event.once(domEvent(document.body, EventType.KEY_DOWN, true)),
Event.once(domEvent(document.body, EventType.MOUSE_DOWN, true))
Event.once(new DomEmitter(document.body, EventType.KEY_DOWN, true).event),
Event.once(new DomEmitter(document.body, EventType.MOUSE_DOWN, true).event)
)).then(async () => {
// Delay the dialog in case the user interacted

View file

@ -68,6 +68,31 @@ export const TEXT_DIFF_EDITOR_ID = 'workbench.editors.textDiffEditor';
*/
export const BINARY_DIFF_EDITOR_ID = 'workbench.editors.binaryResourceDiffEditor';
export interface IEditorDescriptor<T extends IEditorPane> {
/**
* The unique type identifier of the editor. All instances
* of the same `IEditorPane` should have the same type
* identifier.
*/
readonly typeId: string;
/**
* The display name of the editor.
*/
readonly name: string;
/**
* Instantiates the editor pane using the provided services.
*/
instantiate(instantiationService: IInstantiationService): T;
/**
* Whether the descriptor is for the provided editor pane.
*/
describes(editorPane: T): boolean;
}
/**
* The editor pane is the container for workbench editors.
*/
@ -414,7 +439,7 @@ export interface IEditorInput extends IDisposable {
readonly onDidChangeLabel: Event<void>;
/**
* Unique type identifier for this inpput. Every editor input of the
* Unique type identifier for this input. Every editor input of the
* same class should share the same type identifier. The type identifier
* is used for example for serialising/deserialising editor inputs
* via the serialisers of the `IEditorInputFactoryRegistry`.
@ -586,14 +611,6 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
return this.getTitle(Verbosity.SHORT);
}
/**
* Returns the preferred editor for this input. A list of candidate editors is passed in that whee registered
* for the input. This allows subclasses to decide late which editor to use for the input on a case by case basis.
*/
getPreferredEditorId(candidates: string[]): string | undefined {
return firstOrDefault(candidates);
}
/**
* Returns a descriptor suitable for telemetry events.
*
@ -642,6 +659,17 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
return this === otherInput;
}
/**
* If a input was registered onto multiple editors, this method
* will be asked to return the preferred one to use.
*
* @param editors a list of editor descriptors that are candidates
* for the editor input to open in.
*/
prefersEditor<T extends IEditorDescriptor<IEditorPane>>(editors: T[]): T | undefined {
return firstOrDefault(editors);
}
isDisposed(): boolean {
return this.disposed;
}
@ -828,6 +856,12 @@ export class SideBySideEditorInput extends EditorInput {
return this.description;
}
override getTelemetryDescriptor(): { [key: string]: unknown } {
const descriptor = this.primary.getTelemetryDescriptor();
return Object.assign(descriptor, super.getTelemetryDescriptor());
}
override isDirty(): boolean {
return this.primary.isDirty();
}
@ -848,12 +882,6 @@ export class SideBySideEditorInput extends EditorInput {
return this.primary.revert(group, options);
}
override getTelemetryDescriptor(): { [key: string]: unknown } {
const descriptor = this.primary.getTelemetryDescriptor();
return Object.assign(descriptor, super.getTelemetryDescriptor());
}
override matches(otherInput: unknown): boolean {
if (otherInput === this) {
return true;

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EditorModel, EditorInput, SideBySideEditorInput, TEXT_DIFF_EDITOR_ID, BINARY_DIFF_EDITOR_ID, Verbosity } from 'vs/workbench/common/editor';
import { EditorModel, EditorInput, SideBySideEditorInput, TEXT_DIFF_EDITOR_ID, BINARY_DIFF_EDITOR_ID, Verbosity, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor';
import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel';
import { DiffEditorModel } from 'vs/workbench/common/editor/diffEditorModel';
import { TextDiffEditorModel } from 'vs/workbench/common/editor/textDiffEditorModel';
@ -104,8 +104,12 @@ export class DiffEditorInput extends SideBySideEditorInput {
return this.cachedModel;
}
override getPreferredEditorId(candidates: string[]): string {
return this.forceOpenAsBinary ? BINARY_DIFF_EDITOR_ID : TEXT_DIFF_EDITOR_ID;
override prefersEditor<T extends IEditorDescriptor<IEditorPane>>(editors: T[]): T | undefined {
if (this.forceOpenAsBinary) {
return editors.find(editor => editor.typeId === BINARY_DIFF_EDITOR_ID);
}
return editors.find(editor => editor.typeId === TEXT_DIFF_EDITOR_ID);
}
private async createModel(): Promise<DiffEditorModel> {

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane, EditorInputCapabilities } from 'vs/workbench/common/editor';
import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor';
import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput';
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
import { FileOperationError, FileOperationResult, FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files';
@ -264,8 +264,12 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements
return super.isSaving();
}
override getPreferredEditorId(candidates: string[]): string {
return this.forceOpenAs === ForceOpenAs.Binary ? BINARY_FILE_EDITOR_ID : TEXT_FILE_EDITOR_ID;
override prefersEditor<T extends IEditorDescriptor<IEditorPane>>(editors: T[]): T | undefined {
if (this.forceOpenAs === ForceOpenAs.Binary) {
return editors.find(editor => editor.typeId === BINARY_FILE_EDITOR_ID);
}
return editors.find(editor => editor.typeId === TEXT_FILE_EDITOR_ID);
}
override resolve(): Promise<ITextFileEditorModel | BinaryEditorModel> {

View file

@ -221,7 +221,7 @@ export class OutputEditor extends AbstractTextResourceEditor {
return channel ? nls.localize('outputViewWithInputAriaLabel', "{0}, Output panel", channel.label) : nls.localize('outputViewAriaLabel', "Output panel");
}
override async setInput(input: TextResourceEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {//
override async setInput(input: TextResourceEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
const focus = !(options && options.preserveFocus);
if (input.matches(this.input)) {
return;

View file

@ -151,7 +151,7 @@ export class PreferencesEditor extends EditorPane {
this.preferencesRenderers.editFocusedPreference();
}
override setInput(input: PreferencesEditorInput, options: SettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {//
override setInput(input: PreferencesEditorInput, options: SettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
this.defaultSettingsEditorContextKey.set(true);
this.defaultSettingsJSONEditorContextKey.set(true);
if (options && options.query) {

View file

@ -208,7 +208,7 @@ export abstract class SharedDesktopMain extends Disposable {
await result;
}
// Uri Identity
// URI Identity
const uriIdentityService = new UriIdentityService(fileService);
serviceCollection.set(IUriIdentityService, uriIdentityService);

View file

@ -6,7 +6,7 @@
import * as assert from 'assert';
import { EditorPane, EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane';
import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor';
import { EditorInput, EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities } from 'vs/workbench/common/editor';
import { EditorInput, EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
@ -16,7 +16,7 @@ import { workbenchInstantiationService, TestEditorGroupView, TestEditorGroupsSer
import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { URI } from 'vs/base/common/uri';
import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor';
import { EditorDescriptor, EditorRegistry } from 'vs/workbench/browser/editor';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
@ -30,8 +30,8 @@ import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/w
const NullThemeService = new TestThemeService();
let EditorRegistry: IEditorRegistry = Registry.as(EditorExtensions.Editors);
let EditorInputRegistry: IEditorInputFactoryRegistry = Registry.as(EditorExtensions.EditorInputFactories);
const editorRegistry: EditorRegistry = Registry.as(EditorExtensions.Editors);
const editorInputRegistry: IEditorInputFactoryRegistry = Registry.as(EditorExtensions.EditorInputFactories);
class TestEditor extends EditorPane {
@ -75,8 +75,8 @@ class TestInput extends EditorInput {
readonly resource = undefined;
override getPreferredEditorId(ids: string[]) {
return ids[1];
override prefersEditor<T extends IEditorDescriptor<IEditorPane>>(editors: T[]): T | undefined {
return editors[1];
}
override get typeId(): string {
@ -105,85 +105,85 @@ class TestResourceEditorInput extends TextResourceEditorInput { }
suite('Workbench EditorPane', () => {
test('EditorPane API', async () => {
let e = new TestEditor(NullTelemetryService);
let input = new OtherTestInput();
let options = new EditorOptions();
const editor = new TestEditor(NullTelemetryService);
const input = new OtherTestInput();
const options = new EditorOptions();
assert(!e.isVisible());
assert(!e.input);
assert(!editor.isVisible());
assert(!editor.input);
await e.setInput(input, options, Object.create(null), CancellationToken.None);
assert.strictEqual(<any>input, e.input);
await editor.setInput(input, options, Object.create(null), CancellationToken.None);
assert.strictEqual(<any>input, editor.input);
const group = new TestEditorGroupView(1);
e.setVisible(true, group);
assert(e.isVisible());
assert.strictEqual(e.group, group);
editor.setVisible(true, group);
assert(editor.isVisible());
assert.strictEqual(editor.group, group);
input.onWillDispose(() => {
assert(false);
});
e.dispose();
e.clearInput();
e.setVisible(false, group);
assert(!e.isVisible());
assert(!e.input);
assert(!e.getControl());
editor.dispose();
editor.clearInput();
editor.setVisible(false, group);
assert(!editor.isVisible());
assert(!editor.input);
assert(!editor.getControl());
});
test('EditorDescriptor', () => {
let d = EditorDescriptor.create(TestEditor, 'id', 'name');
assert.strictEqual(d.getId(), 'id');
assert.strictEqual(d.getName(), 'name');
const editorDescriptor = EditorDescriptor.create(TestEditor, 'id', 'name');
assert.strictEqual(editorDescriptor.typeId, 'id');
assert.strictEqual(editorDescriptor.name, 'name');
});
test('Editor Registration', function () {
let d1 = EditorDescriptor.create(TestEditor, 'id1', 'name');
let d2 = EditorDescriptor.create(OtherTestEditor, 'id2', 'name');
const editorDescriptor1 = EditorDescriptor.create(TestEditor, 'id1', 'name');
const editorDescriptor2 = EditorDescriptor.create(OtherTestEditor, 'id2', 'name');
let oldEditorsCnt = EditorRegistry.getEditors().length;
let oldInputCnt = (<any>EditorRegistry).getEditorInputs().length;
const oldEditorsCnt = editorRegistry.getEditors().length;
const oldInputCnt = editorRegistry.getEditorInputs().length;
const dispose1 = EditorRegistry.registerEditor(d1, [new SyncDescriptor(TestInput)]);
const dispose2 = EditorRegistry.registerEditor(d2, [new SyncDescriptor(TestInput), new SyncDescriptor(OtherTestInput)]);
const dispose1 = editorRegistry.registerEditor(editorDescriptor1, [new SyncDescriptor(TestInput)]);
const dispose2 = editorRegistry.registerEditor(editorDescriptor2, [new SyncDescriptor(TestInput), new SyncDescriptor(OtherTestInput)]);
assert.strictEqual(EditorRegistry.getEditors().length, oldEditorsCnt + 2);
assert.strictEqual((<any>EditorRegistry).getEditorInputs().length, oldInputCnt + 3);
assert.strictEqual(editorRegistry.getEditors().length, oldEditorsCnt + 2);
assert.strictEqual(editorRegistry.getEditorInputs().length, oldInputCnt + 3);
assert.strictEqual(EditorRegistry.getEditor(new TestInput()), d2);
assert.strictEqual(EditorRegistry.getEditor(new OtherTestInput()), d2);
assert.strictEqual(editorRegistry.getEditor(new TestInput()), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditor(new OtherTestInput()), editorDescriptor2);
assert.strictEqual(EditorRegistry.getEditorById('id1'), d1);
assert.strictEqual(EditorRegistry.getEditorById('id2'), d2);
assert(!EditorRegistry.getEditorById('id3'));
assert.strictEqual(editorRegistry.getEditorByType('id1'), editorDescriptor1);
assert.strictEqual(editorRegistry.getEditorByType('id2'), editorDescriptor2);
assert(!editorRegistry.getEditorByType('id3'));
dispose([dispose1, dispose2]);
});
test('Editor Lookup favors specific class over superclass (match on specific class)', function () {
let d1 = EditorDescriptor.create(TestEditor, 'id1', 'name');
const d1 = EditorDescriptor.create(TestEditor, 'id1', 'name');
const disposables = new DisposableStore();
disposables.add(registerTestResourceEditor());
disposables.add(EditorRegistry.registerEditor(d1, [new SyncDescriptor(TestResourceEditorInput)]));
disposables.add(editorRegistry.registerEditor(d1, [new SyncDescriptor(TestResourceEditorInput)]));
let inst = workbenchInstantiationService();
const inst = workbenchInstantiationService();
const editor = EditorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst);
const editor = editorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst);
assert.strictEqual(editor.getId(), 'testEditor');
const otherEditor = EditorRegistry.getEditor(inst.createInstance(TextResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst);
const otherEditor = editorRegistry.getEditor(inst.createInstance(TextResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst);
assert.strictEqual(otherEditor.getId(), 'workbench.editors.textResourceEditor');
disposables.dispose();
});
test('Editor Lookup favors specific class over superclass (match on super class)', function () {
let inst = workbenchInstantiationService();
const inst = workbenchInstantiationService();
const disposables = new DisposableStore();
disposables.add(registerTestResourceEditor());
const editor = EditorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst);
const editor = editorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst);
assert.strictEqual('workbench.editors.textResourceEditor', editor.getId());
@ -192,17 +192,17 @@ suite('Workbench EditorPane', () => {
test('Editor Input Serializer', function () {
const testInput = new TestEditorInput(URI.file('/fake'), 'testTypeId');
workbenchInstantiationService().invokeFunction(accessor => EditorInputRegistry.start(accessor));
const disposable = EditorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer);
workbenchInstantiationService().invokeFunction(accessor => editorInputRegistry.start(accessor));
const disposable = editorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer);
let factory = EditorInputRegistry.getEditorInputSerializer('testTypeId');
let factory = editorInputRegistry.getEditorInputSerializer('testTypeId');
assert(factory);
factory = EditorInputRegistry.getEditorInputSerializer(testInput);
factory = editorInputRegistry.getEditorInputSerializer(testInput);
assert(factory);
// throws when registering serializer for same type
assert.throws(() => EditorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer));
assert.throws(() => editorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer));
disposable.dispose();
});
@ -283,7 +283,7 @@ suite('Workbench EditorPane', () => {
interface TestViewState { line: number; }
const rawMemento = Object.create(null);
let memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService);
memento.saveEditorState(testGroup0, URI.file('/some/folder/file-1.txt'), { line: 1 });
memento.saveEditorState(testGroup0, URI.file('/some/folder/file-2.txt'), { line: 2 });
@ -326,7 +326,7 @@ suite('Workbench EditorPane', () => {
}
const rawMemento = Object.create(null);
let memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService());
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService());
const testInputA = new TestEditorInput(URI.file('/A'));
@ -364,7 +364,7 @@ suite('Workbench EditorPane', () => {
}
const rawMemento = Object.create(null);
let memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService());
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService());
const testInputA = new TestEditorInput(URI.file('/A'));
@ -401,6 +401,7 @@ suite('Workbench EditorPane', () => {
});
test('WorkspaceTrustRequiredEditor', async function () {
class TrustRequiredTestEditor extends EditorPane {
constructor(@ITelemetryService telemetryService: ITelemetryService) {
super('TestEditor', NullTelemetryService, NullThemeService, new TestStorageService());
@ -443,8 +444,8 @@ suite('Workbench EditorPane', () => {
const group = editorPart.activeGroup;
let editorDescriptor = EditorDescriptor.create(TrustRequiredTestEditor, 'id1', 'name');
disposables.add(EditorRegistry.registerEditor(editorDescriptor, [new SyncDescriptor(TrustRequiredTestInput)]));
const editorDescriptor = EditorDescriptor.create(TrustRequiredTestEditor, 'id1', 'name');
disposables.add(editorRegistry.registerEditor(editorDescriptor, [new SyncDescriptor(TrustRequiredTestInput)]));
const testInput = new TrustRequiredTestInput();