Merge commit 'be3e8236086165e5e45a5a10783823874b3f3ebd' as 'lib/vscode'

This commit is contained in:
Joe Previte
2020-12-15 15:52:33 -07:00
4649 changed files with 1311795 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
import { IEditorInput, GroupIdentifier } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';
export const IHistoryService = createDecorator<IHistoryService>('historyService');
export interface IHistoryService {
readonly _serviceBrand: undefined;
/**
* Re-opens the last closed editor if any.
*/
reopenLastClosedEditor(): void;
/**
* Navigates to the last location where an edit happened.
*/
openLastEditLocation(): void;
/**
* Navigate forwards in history.
*/
forward(): void;
/**
* Navigate backwards in history.
*/
back(): void;
/**
* Navigate forward or backwards to previous entry in history.
*/
last(): void;
/**
* Removes an entry from history.
*/
remove(input: IEditorInput | IResourceEditorInput): void;
/**
* Clears all history.
*/
clear(): void;
/**
* Clear list of recently opened editors.
*/
clearRecentlyOpened(): void;
/**
* Get the entire history of editors that were opened.
*/
getHistory(): ReadonlyArray<IEditorInput | IResourceEditorInput>;
/**
* Looking at the editor history, returns the workspace root of the last file that was
* inside the workspace and part of the editor history.
*
* @param schemeFilter filter to restrict roots by scheme.
*/
getLastActiveWorkspaceRoot(schemeFilter?: string): URI | undefined;
/**
* Looking at the editor history, returns the resource of the last file that was opened.
*
* @param schemeFilter filter to restrict roots by scheme.
*/
getLastActiveFile(schemeFilter: string): URI | undefined;
/**
* Opens the next used editor if any.
*
* @param group optional indicator to scope to a specific group.
*/
openNextRecentlyUsedEditor(group?: GroupIdentifier): void;
/**
* Opens the previously used editor if any.
*
* @param group optional indicator to scope to a specific group.
*/
openPreviouslyUsedEditor(group?: GroupIdentifier): void;
}

View File

@@ -0,0 +1,190 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { EditorOptions } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';
import { workbenchInstantiationService, TestFileEditorInput, registerTestEditor } from 'vs/workbench/test/browser/workbenchTestServices';
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IEditorGroupsService, GroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService';
import { HistoryService } from 'vs/workbench/services/history/browser/history';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { timeout } from 'vs/base/common/async';
const TEST_EDITOR_ID = 'MyTestEditorForEditorHistory';
const TEST_EDITOR_INPUT_ID = 'testEditorInputForHistoyService';
async function createServices(): Promise<[EditorPart, HistoryService, EditorService]> {
const instantiationService = workbenchInstantiationService();
const part = instantiationService.createInstance(EditorPart);
part.create(document.createElement('div'));
part.layout(400, 300);
await part.whenRestored;
instantiationService.stub(IEditorGroupsService, part);
const editorService = instantiationService.createInstance(EditorService);
instantiationService.stub(IEditorService, editorService);
const historyService = instantiationService.createInstance(HistoryService);
instantiationService.stub(IHistoryService, historyService);
return [part, historyService, editorService];
}
suite('HistoryService', function () {
let disposables: IDisposable[] = [];
setup(() => {
disposables.push(registerTestEditor(TEST_EDITOR_ID, [new SyncDescriptor(TestFileEditorInput)]));
});
teardown(() => {
dispose(disposables);
disposables = [];
});
test('back / forward', async () => {
const [part, historyService] = await createServices();
const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID);
await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true }));
assert.equal(part.activeGroup.activeEditor, input1);
const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_EDITOR_INPUT_ID);
await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true }));
assert.equal(part.activeGroup.activeEditor, input2);
historyService.back();
assert.equal(part.activeGroup.activeEditor, input1);
historyService.forward();
assert.equal(part.activeGroup.activeEditor, input2);
part.dispose();
});
test('getHistory', async () => {
const [part, historyService] = await createServices();
let history = historyService.getHistory();
assert.equal(history.length, 0);
const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID);
await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true }));
const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_EDITOR_INPUT_ID);
await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true }));
history = historyService.getHistory();
assert.equal(history.length, 2);
historyService.remove(input2);
history = historyService.getHistory();
assert.equal(history.length, 1);
assert.equal(history[0], input1);
part.dispose();
});
test('getLastActiveFile', async () => {
const [part, historyService] = await createServices();
assert.ok(!historyService.getLastActiveFile('foo'));
const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID);
await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true }));
assert.equal(historyService.getLastActiveFile('foo')?.toString(), input1.resource.toString());
part.dispose();
});
test('open next/previous recently used editor (single group)', async () => {
const [part, historyService] = await createServices();
const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID);
const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_EDITOR_INPUT_ID);
await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true }));
assert.equal(part.activeGroup.activeEditor, input1);
await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true }));
assert.equal(part.activeGroup.activeEditor, input2);
historyService.openPreviouslyUsedEditor();
assert.equal(part.activeGroup.activeEditor, input1);
historyService.openNextRecentlyUsedEditor();
assert.equal(part.activeGroup.activeEditor, input2);
historyService.openPreviouslyUsedEditor(part.activeGroup.id);
assert.equal(part.activeGroup.activeEditor, input1);
historyService.openNextRecentlyUsedEditor(part.activeGroup.id);
assert.equal(part.activeGroup.activeEditor, input2);
part.dispose();
});
test('open next/previous recently used editor (multi group)', async () => {
const [part, historyService] = await createServices();
const rootGroup = part.activeGroup;
const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID);
const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_EDITOR_INPUT_ID);
const sideGroup = part.addGroup(rootGroup, GroupDirection.RIGHT);
await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true }));
await sideGroup.openEditor(input2, EditorOptions.create({ pinned: true }));
historyService.openPreviouslyUsedEditor();
assert.equal(part.activeGroup, rootGroup);
assert.equal(rootGroup.activeEditor, input1);
historyService.openNextRecentlyUsedEditor();
assert.equal(part.activeGroup, sideGroup);
assert.equal(sideGroup.activeEditor, input2);
part.dispose();
});
test('open next/previous recently is reset when other input opens', async () => {
const [part, historyService] = await createServices();
const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID);
const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_EDITOR_INPUT_ID);
const input3 = new TestFileEditorInput(URI.parse('foo://bar3'), TEST_EDITOR_INPUT_ID);
const input4 = new TestFileEditorInput(URI.parse('foo://bar4'), TEST_EDITOR_INPUT_ID);
await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true }));
await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true }));
await part.activeGroup.openEditor(input3, EditorOptions.create({ pinned: true }));
historyService.openPreviouslyUsedEditor();
assert.equal(part.activeGroup.activeEditor, input2);
await timeout(0);
await part.activeGroup.openEditor(input4, EditorOptions.create({ pinned: true }));
historyService.openPreviouslyUsedEditor();
assert.equal(part.activeGroup.activeEditor, input2);
historyService.openNextRecentlyUsedEditor();
assert.equal(part.activeGroup.activeEditor, input4);
part.dispose();
});
});