editors - add and adopt IEditorService#isOpen(resource) for fast lookups of opened editors

This commit is contained in:
Benjamin Pasero 2020-03-02 11:15:21 +01:00
parent f2502971b5
commit 66c09fb60e
11 changed files with 225 additions and 38 deletions

View file

@ -246,7 +246,7 @@ export class ResourcesDropHandler {
}
// File: ensure the file is not dirty or opened already
else if (this.textFileService.isDirty(droppedDirtyEditor.resource) || this.editorService.isOpen(this.editorService.createInput({ resource: droppedDirtyEditor.resource, forceFile: true }))) {
else if (this.textFileService.isDirty(droppedDirtyEditor.resource) || this.editorService.isOpen({ resource: droppedDirtyEditor.resource })) {
return false;
}

View file

@ -1075,7 +1075,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Update model and make sure to continue to use the editor we get from
// the model. It is possible that the editor was already opened and we
// want to ensure that we use the existing instance in that case.
const editor = this.group.getEditorByIndex(currentIndex)!;
const editor = this._group.getEditorByIndex(currentIndex);
if (!editor) {
return;
}
// Update model
this._group.moveEditor(editor, moveToIndex);
@ -1278,7 +1281,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return false; // editor must be dirty and not saving
}
if (editor instanceof SideBySideEditorInput && this.isOpened(editor.master)) {
if (editor instanceof SideBySideEditorInput && this._group.contains(editor.master)) {
return false; // master-side of editor is still opened somewhere else
}

View file

@ -3,15 +3,16 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IEditorInput, IEditorInputFactoryRegistry, IEditorIdentifier, GroupIdentifier, Extensions, IEditorPartOptionsChangeEvent, EditorsOrder } from 'vs/workbench/common/editor';
import { IEditorInput, IEditorInputFactoryRegistry, IEditorIdentifier, GroupIdentifier, Extensions, IEditorPartOptionsChangeEvent, EditorsOrder, toResource, SideBySideEditor } from 'vs/workbench/common/editor';
import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { Registry } from 'vs/platform/registry/common/platform';
import { Event, Emitter } from 'vs/base/common/event';
import { IEditorGroupsService, IEditorGroup, GroupChangeKind, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService';
import { coalesce } from 'vs/base/common/arrays';
import { LinkedMap, Touch } from 'vs/base/common/map';
import { LinkedMap, Touch, ResourceMap } from 'vs/base/common/map';
import { equals } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
interface ISerializedEditorsList {
entries: ISerializedEditorIdentifier[];
@ -37,9 +38,10 @@ export class EditorsObserver extends Disposable {
private readonly keyMap = new Map<GroupIdentifier, Map<IEditorInput, IEditorIdentifier>>();
private readonly mostRecentEditorsMap = new LinkedMap<IEditorIdentifier, IEditorIdentifier>();
private readonly editorResourcesMap = new ResourceMap<number>();
private readonly _onDidChange = this._register(new Emitter<void>());
readonly onDidChange = this._onDidChange.event;
private readonly _onDidMostRecentlyActiveEditorsChange = this._register(new Emitter<void>());
readonly onDidMostRecentlyActiveEditorsChange = this._onDidMostRecentlyActiveEditorsChange.event;
get count(): number {
return this.mostRecentEditorsMap.size;
@ -49,6 +51,10 @@ export class EditorsObserver extends Disposable {
return this.mostRecentEditorsMap.values();
}
hasEditor(resource: URI): boolean {
return this.editorResourcesMap.has(resource);
}
constructor(
@IEditorGroupsService private editorGroupsService: IEditorGroupsService,
@IStorageService private readonly storageService: IStorageService
@ -72,12 +78,12 @@ export class EditorsObserver extends Disposable {
// of the new group into our list in LRU order
const groupEditorsMru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE);
for (let i = groupEditorsMru.length - 1; i >= 0; i--) {
this.addMostRecentEditor(group, groupEditorsMru[i], false /* is not active */);
this.addMostRecentEditor(group, groupEditorsMru[i], false /* is not active */, true /* is new */);
}
// Make sure that active editor is put as first if group is active
if (this.editorGroupsService.activeGroup === group && group.activeEditor) {
this.addMostRecentEditor(group, group.activeEditor, true /* is active */);
this.addMostRecentEditor(group, group.activeEditor, true /* is active */, false /* already added before */);
}
// Group Listeners
@ -92,7 +98,7 @@ export class EditorsObserver extends Disposable {
// Group gets active: put active editor as most recent
case GroupChangeKind.GROUP_ACTIVE: {
if (this.editorGroupsService.activeGroup === group && group.activeEditor) {
this.addMostRecentEditor(group, group.activeEditor, true /* is active */);
this.addMostRecentEditor(group, group.activeEditor, true /* is active */, false /* editor already opened */);
}
break;
@ -102,7 +108,7 @@ export class EditorsObserver extends Disposable {
// if group is active, otherwise second most recent
case GroupChangeKind.EDITOR_ACTIVE: {
if (e.editor) {
this.addMostRecentEditor(group, e.editor, this.editorGroupsService.activeGroup === group);
this.addMostRecentEditor(group, e.editor, this.editorGroupsService.activeGroup === group, false /* editor already opened */);
}
break;
@ -114,7 +120,7 @@ export class EditorsObserver extends Disposable {
// start to close oldest ones if needed.
case GroupChangeKind.EDITOR_OPEN: {
if (e.editor) {
this.addMostRecentEditor(group, e.editor, false /* is not active */);
this.addMostRecentEditor(group, e.editor, false /* is not active */, true /* is new */);
this.ensureOpenedEditorsLimit({ groupId: group.id, editor: e.editor }, group.id);
}
@ -148,7 +154,7 @@ export class EditorsObserver extends Disposable {
}
}
private addMostRecentEditor(group: IEditorGroup, editor: IEditorInput, isActive: boolean): void {
private addMostRecentEditor(group: IEditorGroup, editor: IEditorInput, isActive: boolean, isNew: boolean): void {
const key = this.ensureKey(group, editor);
const mostRecentEditor = this.mostRecentEditorsMap.first;
@ -169,11 +175,39 @@ export class EditorsObserver extends Disposable {
this.mostRecentEditorsMap.set(mostRecentEditor, mostRecentEditor, Touch.AsOld /* make first */);
}
// Update in resource map if this is a new editor
if (isNew) {
this.updateEditorResourcesMap(editor, true);
}
// Event
this._onDidChange.fire();
this._onDidMostRecentlyActiveEditorsChange.fire();
}
private updateEditorResourcesMap(editor: IEditorInput, add: boolean): void {
const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER });
if (!resource) {
return; // require a resource
}
if (add) {
this.editorResourcesMap.set(resource, (this.editorResourcesMap.get(resource) ?? 0) + 1);
} else {
const counter = this.editorResourcesMap.get(resource) ?? 0;
if (counter > 1) {
this.editorResourcesMap.set(resource, counter - 1);
} else {
this.editorResourcesMap.delete(resource);
}
}
}
private removeMostRecentEditor(group: IEditorGroup, editor: IEditorInput): void {
// Update in resource map
this.updateEditorResourcesMap(editor, false);
// Update in MRU list
const key = this.findKey(group, editor);
if (key) {
@ -187,7 +221,7 @@ export class EditorsObserver extends Disposable {
}
// Event
this._onDidChange.fire();
this._onDidMostRecentlyActiveEditorsChange.fire();
}
}
@ -361,7 +395,7 @@ export class EditorsObserver extends Disposable {
const group = groups[i];
const groupEditorsMru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE);
for (let i = groupEditorsMru.length - 1; i >= 0; i--) {
this.addMostRecentEditor(group, groupEditorsMru[i], true /* enforce as active to preserve order */);
this.addMostRecentEditor(group, groupEditorsMru[i], true /* enforce as active to preserve order */, true /* is new */);
}
}
}
@ -392,6 +426,9 @@ export class EditorsObserver extends Disposable {
// Make sure key is registered as well
const editorIdentifier = this.ensureKey(group, editor);
mapValues.push([editorIdentifier, editorIdentifier]);
// Update in resource map
this.updateEditorResourcesMap(editor, true);
}
// Fill map with deserialized values

View file

@ -13,7 +13,6 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { RunOnceWorker } from 'vs/base/common/async';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { Schemas } from 'vs/base/common/network';
export class TextFileEditorTracker extends Disposable implements IWorkbenchContribution {
@ -45,7 +44,7 @@ export class TextFileEditorTracker extends Disposable implements IWorkbenchContr
//#region Text File: Ensure every dirty text and untitled file is opened in an editor
private readonly ensureDirtyFilesAreOpenedWorker = this._register(new RunOnceWorker<URI>(units => this.ensureDirtyTextFilesAreOpened(units), 250));
private readonly ensureDirtyFilesAreOpenedWorker = this._register(new RunOnceWorker<URI>(units => this.ensureDirtyTextFilesAreOpened(units), 50));
private ensureDirtyTextFilesAreOpened(resources: URI[]): void {
this.doEnsureDirtyTextFilesAreOpened(distinct(resources.filter(resource => {
@ -58,7 +57,7 @@ export class TextFileEditorTracker extends Disposable implements IWorkbenchContr
return false; // resource must not be pending to save
}
if (this.editorService.isOpen(this.editorService.createInput({ resource, forceFile: resource.scheme !== Schemas.untitled, forceUntitled: resource.scheme === Schemas.untitled }))) {
if (this.editorService.isOpen({ resource })) {
return false; // model must not be opened already as file
}

View file

@ -677,7 +677,7 @@ class OpenEditorsDragAndDrop implements IListDragAndDrop<OpenEditor | IEditorGro
drop(data: IDragAndDropData, targetElement: OpenEditor | IEditorGroup, _targetIndex: number, originalEvent: DragEvent): void {
const group = targetElement instanceof OpenEditor ? targetElement.group : targetElement;
const index = targetElement instanceof OpenEditor ? targetElement.group.getIndexOfEditor(targetElement.editor) : 0;
const index = targetElement instanceof OpenEditor ? targetElement.editorIndex : 0;
if (data instanceof ElementsDragAndDropData) {
const elementsData = data.elements;

View file

@ -84,7 +84,7 @@ export class EditorService extends Disposable implements EditorServiceImpl {
this.editorGroupService.whenRestored.then(() => this.onEditorsRestored());
this.editorGroupService.onDidActiveGroupChange(group => this.handleActiveEditorChange(group));
this.editorGroupService.onDidAddGroup(group => this.registerGroupListeners(group as IEditorGroupView));
this.editorsObserver.onDidChange(() => this._onDidMostRecentlyActiveEditorsChange.fire());
this.editorsObserver.onDidMostRecentlyActiveEditorsChange(() => this._onDidMostRecentlyActiveEditorsChange.fire());
// Out of workspace file watchers
this._register(this.onDidVisibleEditorsChange(() => this.handleVisibleEditorsChange()));
@ -705,8 +705,18 @@ export class EditorService extends Disposable implements EditorServiceImpl {
//#region isOpen()
isOpen(editor: IEditorInput): boolean {
return this.editorGroupService.groups.some(group => group.isOpened(editor));
isOpen(editor: IEditorInput): boolean;
isOpen(editor: IResourceInput): boolean;
isOpen(editor: IEditorInput | IResourceInput): boolean {
if (editor instanceof EditorInput) {
return this.editorGroupService.groups.some(group => group.isOpened(editor));
}
if (editor.resource) {
return this.editorsObserver.hasEditor(editor.resource);
}
return false;
}
//#endregion
@ -1169,7 +1179,9 @@ export class DelegatingEditorService implements IEditorService {
return this.editorService.replaceEditors(editors as IResourceEditorReplacement[] /* TS fail */, group);
}
isOpen(editor: IEditorInput): boolean { return this.editorService.isOpen(editor); }
isOpen(editor: IEditorInput): boolean;
isOpen(editor: IResourceInput): boolean;
isOpen(editor: IEditorInput | IResourceInput): boolean { return this.editorService.isOpen(editor as IResourceInput /* TS fail */); }
overrideOpenEditor(handler: IOpenEditorOverrideHandler): IDisposable { return this.editorService.overrideOpenEditor(handler); }

View file

@ -196,7 +196,13 @@ export interface IEditorService {
* Find out if the provided editor is opened in any editor group.
*
* Note: An editor can be opened but not actively visible.
*
* @param editor the editor to check for being opened. If a
* `IResourceInput` is passed in, the resource is checked on
* all opened editors. In case of a side by side editor, the
* right hand side resource is considered only.
*/
isOpen(editor: IResourceInput): boolean;
isOpen(editor: IEditorInput): boolean;
/**

View file

@ -105,6 +105,7 @@ suite('EditorService', () => {
assert.ok(!service.activeTextEditorMode);
assert.equal(service.visibleTextEditorWidgets.length, 0);
assert.equal(service.isOpen(input), true);
assert.equal(service.isOpen({ resource: input.resource }), true);
assert.equal(activeEditorChangeEventCounter, 1);
assert.equal(visibleEditorChangeEventCounter, 1);
@ -137,7 +138,9 @@ suite('EditorService', () => {
assert.equal(otherInput, service.getEditors(EditorsOrder.SEQUENTIAL)[1].editor);
assert.equal(service.visibleControls.length, 1);
assert.equal(service.isOpen(input), true);
assert.equal(service.isOpen({ resource: input.resource }), true);
assert.equal(service.isOpen(otherInput), true);
assert.equal(service.isOpen({ resource: otherInput.resource }), true);
assert.equal(activeEditorChangeEventCounter, 4);
assert.equal(visibleEditorChangeEventCounter, 4);
@ -149,6 +152,53 @@ suite('EditorService', () => {
part.dispose();
});
test('isOpen() with side by side editor', async () => {
const [part, service] = createEditorService();
const input = new TestFileEditorInput(URI.parse('my://resource-openEditors'), TEST_EDITOR_INPUT_ID);
const otherInput = new TestFileEditorInput(URI.parse('my://resource2-openEditors'), TEST_EDITOR_INPUT_ID);
const sideBySideInput = new SideBySideEditorInput('sideBySide', '', input, otherInput);
await part.whenRestored;
const editor1 = await service.openEditor(sideBySideInput, { pinned: true });
assert.equal(part.activeGroup.count, 1);
assert.equal(service.isOpen(input), false);
assert.equal(service.isOpen(otherInput), false);
assert.equal(service.isOpen(sideBySideInput), true);
assert.equal(service.isOpen({ resource: input.resource }), false);
assert.equal(service.isOpen({ resource: otherInput.resource }), true);
const editor2 = await service.openEditor(input, { pinned: true });
assert.equal(part.activeGroup.count, 2);
assert.equal(service.isOpen(input), true);
assert.equal(service.isOpen(otherInput), false);
assert.equal(service.isOpen(sideBySideInput), true);
assert.equal(service.isOpen({ resource: input.resource }), true);
assert.equal(service.isOpen({ resource: otherInput.resource }), true);
await editor2?.group?.closeEditor(input);
assert.equal(part.activeGroup.count, 1);
assert.equal(service.isOpen(input), false);
assert.equal(service.isOpen(otherInput), false);
assert.equal(service.isOpen(sideBySideInput), true);
assert.equal(service.isOpen({ resource: input.resource }), false);
assert.equal(service.isOpen({ resource: otherInput.resource }), true);
await editor1?.group?.closeEditor(sideBySideInput);
assert.equal(service.isOpen(input), false);
assert.equal(service.isOpen(otherInput), false);
assert.equal(service.isOpen(sideBySideInput), false);
assert.equal(service.isOpen({ resource: input.resource }), false);
assert.equal(service.isOpen({ resource: otherInput.resource }), false);
part.dispose();
});
test('openEditors() / replaceEditors()', async () => {
const [part, service] = createEditorService();

View file

@ -6,7 +6,7 @@
import * as assert from 'assert';
import { EditorOptions, IEditorInputFactoryRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';
import { workbenchInstantiationService, TestStorageService, TestFileEditorInput, registerTestEditor } from 'vs/workbench/test/browser/workbenchTestServices';
import { workbenchInstantiationService, TestStorageService, TestFileEditorInput, registerTestEditor, TestEditorPart } from 'vs/workbench/test/browser/workbenchTestServices';
import { Registry } from 'vs/platform/registry/common/platform';
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
@ -34,11 +34,11 @@ suite('EditorsObserver', function () {
disposables = [];
});
async function createPart(): Promise<EditorPart> {
async function createPart(): Promise<TestEditorPart> {
const instantiationService = workbenchInstantiationService();
instantiationService.invokeFunction(accessor => Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor));
const part = instantiationService.createInstance(EditorPart);
const part = instantiationService.createInstance(TestEditorPart);
part.create(document.createElement('div'));
part.layout(400, 300);
@ -58,14 +58,14 @@ suite('EditorsObserver', function () {
test('basics (single group)', async () => {
const [part, observer] = await createEditorObserver();
let observerChangeListenerCalled = false;
const listener = observer.onDidChange(() => {
observerChangeListenerCalled = true;
let onDidMostRecentlyActiveEditorsChangeCalled = false;
const listener = observer.onDidMostRecentlyActiveEditorsChange(() => {
onDidMostRecentlyActiveEditorsChangeCalled = true;
});
let currentEditorsMRU = observer.editors;
assert.equal(currentEditorsMRU.length, 0);
assert.equal(observerChangeListenerCalled, false);
assert.equal(onDidMostRecentlyActiveEditorsChangeCalled, false);
const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_SERIALIZABLE_EDITOR_INPUT_ID);
@ -75,7 +75,8 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU.length, 1);
assert.equal(currentEditorsMRU[0].groupId, part.activeGroup.id);
assert.equal(currentEditorsMRU[0].editor, input1);
assert.equal(observerChangeListenerCalled, true);
assert.equal(onDidMostRecentlyActiveEditorsChangeCalled, true);
assert.equal(observer.hasEditor(input1.resource), true);
const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_SERIALIZABLE_EDITOR_INPUT_ID);
const input3 = new TestFileEditorInput(URI.parse('foo://bar3'), TEST_SERIALIZABLE_EDITOR_INPUT_ID);
@ -91,6 +92,8 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[1].editor, input2);
assert.equal(currentEditorsMRU[2].groupId, part.activeGroup.id);
assert.equal(currentEditorsMRU[2].editor, input1);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true }));
@ -102,8 +105,11 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[1].editor, input3);
assert.equal(currentEditorsMRU[2].groupId, part.activeGroup.id);
assert.equal(currentEditorsMRU[2].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
observerChangeListenerCalled = false;
onDidMostRecentlyActiveEditorsChangeCalled = false;
await part.activeGroup.closeEditor(input1);
currentEditorsMRU = observer.editors;
@ -112,11 +118,17 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[0].editor, input2);
assert.equal(currentEditorsMRU[1].groupId, part.activeGroup.id);
assert.equal(currentEditorsMRU[1].editor, input3);
assert.equal(observerChangeListenerCalled, true);
assert.equal(onDidMostRecentlyActiveEditorsChangeCalled, true);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
await part.activeGroup.closeAllEditors();
currentEditorsMRU = observer.editors;
assert.equal(currentEditorsMRU.length, 0);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), false);
assert.equal(observer.hasEditor(input3.resource), false);
part.dispose();
listener.dispose();
@ -143,6 +155,7 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[0].editor, input1);
assert.equal(currentEditorsMRU[1].groupId, rootGroup.id);
assert.equal(currentEditorsMRU[1].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true, activation: EditorActivation.ACTIVATE }));
@ -152,6 +165,7 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[0].editor, input1);
assert.equal(currentEditorsMRU[1].groupId, sideGroup.id);
assert.equal(currentEditorsMRU[1].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
// Opening an editor inactive should not change
// the most recent editor, but rather put it behind
@ -167,6 +181,8 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[1].editor, input2);
assert.equal(currentEditorsMRU[2].groupId, sideGroup.id);
assert.equal(currentEditorsMRU[2].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), true);
await rootGroup.closeAllEditors();
@ -174,11 +190,15 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU.length, 1);
assert.equal(currentEditorsMRU[0].groupId, sideGroup.id);
assert.equal(currentEditorsMRU[0].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), false);
await sideGroup.closeAllEditors();
currentEditorsMRU = observer.editors;
assert.equal(currentEditorsMRU.length, 0);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), false);
part.dispose();
});
@ -204,6 +224,9 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[1].editor, input2);
assert.equal(currentEditorsMRU[2].groupId, rootGroup.id);
assert.equal(currentEditorsMRU[2].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
const copiedGroup = part.copyGroup(rootGroup, rootGroup, GroupDirection.RIGHT);
copiedGroup.setActive(true);
@ -222,6 +245,21 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[4].editor, input2);
assert.equal(currentEditorsMRU[5].groupId, rootGroup.id);
assert.equal(currentEditorsMRU[5].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
await rootGroup.closeAllEditors();
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
await copiedGroup.closeAllEditors();
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), false);
assert.equal(observer.hasEditor(input3.resource), false);
part.dispose();
});
@ -251,6 +289,9 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[1].editor, input2);
assert.equal(currentEditorsMRU[2].groupId, rootGroup.id);
assert.equal(currentEditorsMRU[2].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
storage._onWillSaveState.fire({ reason: WillSaveStateReason.SHUTDOWN });
@ -265,7 +306,11 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[1].editor, input2);
assert.equal(currentEditorsMRU[2].groupId, rootGroup.id);
assert.equal(currentEditorsMRU[2].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
part.clearState();
part.dispose();
});
@ -296,6 +341,9 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[1].editor, input2);
assert.equal(currentEditorsMRU[2].groupId, rootGroup.id);
assert.equal(currentEditorsMRU[2].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
storage._onWillSaveState.fire({ reason: WillSaveStateReason.SHUTDOWN });
@ -310,7 +358,11 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU[1].editor, input2);
assert.equal(currentEditorsMRU[2].groupId, rootGroup.id);
assert.equal(currentEditorsMRU[2].editor, input1);
assert.equal(restoredObserver.hasEditor(input1.resource), true);
assert.equal(restoredObserver.hasEditor(input2.resource), true);
assert.equal(restoredObserver.hasEditor(input3.resource), true);
part.clearState();
part.dispose();
});
@ -331,6 +383,7 @@ suite('EditorsObserver', function () {
assert.equal(currentEditorsMRU.length, 1);
assert.equal(currentEditorsMRU[0].groupId, rootGroup.id);
assert.equal(currentEditorsMRU[0].editor, input1);
assert.equal(observer.hasEditor(input1.resource), true);
storage._onWillSaveState.fire({ reason: WillSaveStateReason.SHUTDOWN });
@ -339,7 +392,9 @@ suite('EditorsObserver', function () {
currentEditorsMRU = restoredObserver.editors;
assert.equal(currentEditorsMRU.length, 0);
assert.equal(restoredObserver.hasEditor(input1.resource), false);
part.clearState();
part.dispose();
});
@ -368,6 +423,10 @@ suite('EditorsObserver', function () {
assert.equal(rootGroup.isOpened(input2), true);
assert.equal(rootGroup.isOpened(input3), true);
assert.equal(rootGroup.isOpened(input4), true);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
assert.equal(observer.hasEditor(input4.resource), true);
input2.setDirty();
part.enforcePartOptions({ limit: { enabled: true, value: 1 } });
@ -379,6 +438,10 @@ suite('EditorsObserver', function () {
assert.equal(rootGroup.isOpened(input2), true); // dirty
assert.equal(rootGroup.isOpened(input3), false);
assert.equal(rootGroup.isOpened(input4), true);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), false);
assert.equal(observer.hasEditor(input4.resource), true);
const input5 = new TestFileEditorInput(URI.parse('foo://bar5'), TEST_EDITOR_INPUT_ID);
await sideGroup.openEditor(input5, EditorOptions.create({ pinned: true }));
@ -388,8 +451,12 @@ suite('EditorsObserver', function () {
assert.equal(rootGroup.isOpened(input2), true); // dirty
assert.equal(rootGroup.isOpened(input3), false);
assert.equal(rootGroup.isOpened(input4), false);
assert.equal(sideGroup.isOpened(input5), true);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), false);
assert.equal(observer.hasEditor(input4.resource), false);
assert.equal(observer.hasEditor(input5.resource), true);
observer.dispose();
part.dispose();
@ -415,11 +482,15 @@ suite('EditorsObserver', function () {
await rootGroup.openEditor(input3, EditorOptions.create({ pinned: true }));
await rootGroup.openEditor(input4, EditorOptions.create({ pinned: true }));
assert.equal(rootGroup.count, 3);
assert.equal(rootGroup.count, 3); // 1 editor got closed due to our limit!
assert.equal(rootGroup.isOpened(input1), false);
assert.equal(rootGroup.isOpened(input2), true);
assert.equal(rootGroup.isOpened(input3), true);
assert.equal(rootGroup.isOpened(input4), true);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
assert.equal(observer.hasEditor(input4.resource), true);
await sideGroup.openEditor(input1, EditorOptions.create({ pinned: true }));
await sideGroup.openEditor(input2, EditorOptions.create({ pinned: true }));
@ -431,6 +502,10 @@ suite('EditorsObserver', function () {
assert.equal(sideGroup.isOpened(input2), true);
assert.equal(sideGroup.isOpened(input3), true);
assert.equal(sideGroup.isOpened(input4), true);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), true);
assert.equal(observer.hasEditor(input3.resource), true);
assert.equal(observer.hasEditor(input4.resource), true);
part.enforcePartOptions({ limit: { enabled: true, value: 1, perEditorGroup: true } });
@ -448,6 +523,11 @@ suite('EditorsObserver', function () {
assert.equal(sideGroup.isOpened(input3), false);
assert.equal(sideGroup.isOpened(input4), true);
assert.equal(observer.hasEditor(input1.resource), false);
assert.equal(observer.hasEditor(input2.resource), false);
assert.equal(observer.hasEditor(input3.resource), false);
assert.equal(observer.hasEditor(input4.resource), true);
observer.dispose();
part.dispose();
});

View file

@ -390,7 +390,7 @@ export class SearchService extends Disposable implements ISearchService {
}
// Skip files that are not opened as text file
if (!this.editorService.isOpen(this.editorService.createInput({ resource, forceFile: resource.scheme !== Schemas.untitled, forceUntitled: resource.scheme === Schemas.untitled }))) {
if (!this.editorService.isOpen({ resource })) {
return;
}

View file

@ -623,7 +623,7 @@ export class TestEditorService implements EditorServiceImpl {
return [this.editorGroupService.activeGroup, editor as EditorInput, undefined];
}
openEditors(_editors: any, _group?: any): Promise<IEditor[]> { throw new Error('not implemented'); }
isOpen(_editor: IEditorInput): boolean { return false; }
isOpen(_editor: IEditorInput | IResourceInput): boolean { return false; }
replaceEditors(_editors: any, _group: any) { return Promise.resolve(undefined); }
invokeWithinEditorContext<T>(fn: (accessor: ServicesAccessor) => T): T { throw new Error('not implemented'); }
createInput(_input: IResourceInput | IUntitledTextResourceInput | IResourceDiffInput | IResourceSideBySideInput): EditorInput { throw new Error('not implemented'); }