Merge from vscode e3c4990c67c40213af168300d1cfeb71d680f877 (#16569)

This commit is contained in:
Cory Rivera
2021-08-25 16:28:29 -07:00
committed by GitHub
parent ab1112bfb3
commit cb7b7da0a4
1752 changed files with 59525 additions and 33878 deletions

View File

@@ -49,7 +49,7 @@ import 'vs/editor/contrib/parameterHints/provideSignatureHelp';
import 'vs/editor/contrib/smartSelect/smartSelect';
import 'vs/editor/contrib/suggest/suggest';
import 'vs/editor/contrib/rename/rename';
import 'vs/editor/contrib/inlineHints/inlineHintsController';
import 'vs/editor/contrib/inlayHints/inlayHintsController';
const defaultSelector = { scheme: 'far' };
const model: ITextModel = createTextModel(
@@ -1204,85 +1204,74 @@ suite('ExtHostLanguageFeatureCommands', function () {
// --- inline hints
test('Inline Hints, back and forth', async function () {
disposables.push(extHost.registerInlineHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlineHintsProvider>{
provideInlineHints() {
return [new types.InlineHint('Foo', new types.Range(0, 1, 2, 3))];
test('Inlay Hints, back and forth', async function () {
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
provideInlayHints() {
return [new types.InlayHint('Foo', new types.Position(0, 1))];
}
}));
await rpcProtocol.sync();
const value = await commands.executeCommand<vscode.InlineHint[]>('vscode.executeInlineHintProvider', model.uri, new types.Range(0, 0, 20, 20));
const value = await commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', model.uri, new types.Range(0, 0, 20, 20));
assert.strictEqual(value.length, 1);
const [first] = value;
assert.strictEqual(first.text, 'Foo');
assert.strictEqual(first.range.start.line, 0);
assert.strictEqual(first.range.start.character, 1);
assert.strictEqual(first.range.end.line, 2);
assert.strictEqual(first.range.end.character, 3);
assert.strictEqual(first.position.line, 0);
assert.strictEqual(first.position.character, 1);
});
test('Inline Hints, merge', async function () {
disposables.push(extHost.registerInlineHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlineHintsProvider>{
provideInlineHints() {
return [new types.InlineHint('Bar', new types.Range(10, 11, 12, 13))];
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
provideInlayHints() {
return [new types.InlayHint('Bar', new types.Position(10, 11))];
}
}));
disposables.push(extHost.registerInlineHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlineHintsProvider>{
provideInlineHints() {
const hint = new types.InlineHint('Foo', new types.Range(0, 1, 2, 3), types.InlineHintKind.Parameter);
hint.description = new types.MarkdownString('**Hello**');
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
provideInlayHints() {
const hint = new types.InlayHint('Foo', new types.Position(0, 1), types.InlayHintKind.Parameter);
return [hint];
}
}));
await rpcProtocol.sync();
const value = await commands.executeCommand<vscode.InlineHint[]>('vscode.executeInlineHintProvider', model.uri, new types.Range(0, 0, 20, 20));
const value = await commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', model.uri, new types.Range(0, 0, 20, 20));
assert.strictEqual(value.length, 2);
const [first, second] = value;
assert.strictEqual(first.text, 'Foo');
assert.strictEqual(first.range.start.line, 0);
assert.strictEqual(first.range.start.character, 1);
assert.strictEqual(first.range.end.line, 2);
assert.strictEqual(first.range.end.character, 3);
assert.ok(first.description instanceof types.MarkdownString);
assert.strictEqual((<types.MarkdownString>first.description).value, '**Hello**');
assert.strictEqual(first.position.line, 0);
assert.strictEqual(first.position.character, 1);
assert.strictEqual(second.text, 'Bar');
assert.strictEqual(second.range.start.line, 10);
assert.strictEqual(second.range.start.character, 11);
assert.strictEqual(second.range.end.line, 12);
assert.strictEqual(second.range.end.character, 13);
assert.strictEqual(second.position.line, 10);
assert.strictEqual(second.position.character, 11);
});
test('Inline Hints, bad provider', async function () {
disposables.push(extHost.registerInlineHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlineHintsProvider>{
provideInlineHints() {
return [new types.InlineHint('Foo', new types.Range(0, 1, 2, 3))];
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
provideInlayHints() {
return [new types.InlayHint('Foo', new types.Position(0, 1))];
}
}));
disposables.push(extHost.registerInlineHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlineHintsProvider>{
provideInlineHints() {
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
provideInlayHints() {
throw new Error();
}
}));
await rpcProtocol.sync();
const value = await commands.executeCommand<vscode.InlineHint[]>('vscode.executeInlineHintProvider', model.uri, new types.Range(0, 0, 20, 20));
const value = await commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', model.uri, new types.Range(0, 0, 20, 20));
assert.strictEqual(value.length, 1);
const [first] = value;
assert.strictEqual(first.text, 'Foo');
assert.strictEqual(first.range.start.line, 0);
assert.strictEqual(first.range.start.character, 1);
assert.strictEqual(first.range.end.line, 2);
assert.strictEqual(first.range.end.character, 3);
assert.strictEqual(first.position.line, 0);
assert.strictEqual(first.position.character, 1);
});
// --- selection ranges

View File

@@ -13,7 +13,7 @@ import { mock } from 'vs/base/test/common/mock';
import { IModelAddedData, MainContext, MainThreadCommandsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
import { ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
import { CellKind, CellUri, NotebookCellExecutionState, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, CellUri, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { URI } from 'vs/base/common/uri';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
@@ -22,6 +22,7 @@ import { isEqual } from 'vs/base/common/resources';
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
import { generateUuid } from 'vs/base/common/uuid';
import { Event } from 'vs/base/common/event';
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
suite('NotebookCell#Document', function () {
@@ -31,6 +32,8 @@ suite('NotebookCell#Document', function () {
let extHostDocumentsAndEditors: ExtHostDocumentsAndEditors;
let extHostDocuments: ExtHostDocuments;
let extHostNotebooks: ExtHostNotebookController;
let extHostNotebookDocuments: ExtHostNotebookDocuments;
const notebookUri = URI.parse('test:///notebook.file');
const disposables = new DisposableStore();
@@ -54,7 +57,9 @@ suite('NotebookCell#Document', function () {
return URI.from({ scheme: 'test', path: generateUuid() });
}
};
extHostNotebooks = new ExtHostNotebookController(rpcProtocol, new ExtHostCommands(rpcProtocol, new NullLogService()), extHostDocumentsAndEditors, extHostDocuments, new NullLogService(), extHostStoragePaths);
extHostNotebooks = new ExtHostNotebookController(rpcProtocol, new ExtHostCommands(rpcProtocol, new NullLogService()), extHostDocumentsAndEditors, extHostDocuments, extHostStoragePaths);
extHostNotebookDocuments = new ExtHostNotebookDocuments(new NullLogService(), extHostNotebooks);
let reg = extHostNotebooks.registerNotebookContentProvider(nullExtensionDescription, 'test', new class extends mock<vscode.NotebookContentProvider>() {
// async openNotebook() { }
});
@@ -69,7 +74,7 @@ suite('NotebookCell#Document', function () {
source: ['### Heading'],
eol: '\n',
language: 'markdown',
cellKind: CellKind.Markdown,
cellKind: CellKind.Markup,
outputs: [],
}, {
handle: 1,
@@ -162,7 +167,7 @@ suite('NotebookCell#Document', function () {
});
});
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -238,7 +243,7 @@ suite('NotebookCell#Document', function () {
assert.strictEqual(notebook.apiNotebook.cellCount, 2);
const [cell1, cell2] = notebook.apiNotebook.getCells();
extHostNotebooks.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
versionId: 2,
rawEvents: [
{
@@ -269,7 +274,7 @@ suite('NotebookCell#Document', function () {
assert.strictEqual(second.index, 1);
// remove first cell
extHostNotebooks.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
@@ -280,7 +285,7 @@ suite('NotebookCell#Document', function () {
assert.strictEqual(notebook.apiNotebook.cellCount, 1);
assert.strictEqual(second.index, 0);
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
@@ -315,7 +320,7 @@ suite('NotebookCell#Document', function () {
// DON'T call this, make sure the cell-documents have not been created yet
// assert.strictEqual(notebook.notebookDocument.cellCount, 2);
extHostNotebooks.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
versionId: 100,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
@@ -325,7 +330,7 @@ suite('NotebookCell#Document', function () {
source: ['### Heading'],
eol: '\n',
language: 'markdown',
cellKind: CellKind.Markdown,
cellKind: CellKind.Markup,
outputs: [],
}, {
handle: 4,
@@ -398,7 +403,7 @@ suite('NotebookCell#Document', function () {
const removed = Event.toPromise(extHostDocuments.onDidRemoveDocument);
const added = Event.toPromise(extHostDocuments.onDidAddDocument);
extHostNotebooks.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
versionId: 12, rawEvents: [{
kind: NotebookCellsChangeType.ChangeLanguage,
index: 0,
@@ -412,30 +417,4 @@ suite('NotebookCell#Document', function () {
assert.strictEqual(first.document.languageId, 'fooLang');
assert.ok(removedDoc === addedDoc);
});
test('change cell execution state does not trigger onDidChangeMetadata event', async function () {
let didFireOnDidChangeMetadata = false;
let e = extHostNotebooks.onDidChangeCellMetadata(() => {
didFireOnDidChangeMetadata = true;
});
const changeExeState = Event.toPromise(extHostNotebooks.onDidChangeNotebookCellExecutionState);
extHostNotebooks.$acceptModelChanged(notebook.uri, {
versionId: 12, rawEvents: [{
kind: NotebookCellsChangeType.ChangeCellMetadata,
index: 0,
metadata: {
...notebook.getCellFromIndex(0)?.internalMetadata,
...{
runState: NotebookCellExecutionState.Executing
}
}
}]
}, false);
await changeExeState;
assert.strictEqual(didFireOnDidChangeMetadata, false);
e.dispose();
});
});

View File

@@ -22,6 +22,7 @@ import { MainContext, MainThreadCommandsShape, MainThreadNotebookShape } from 'v
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
import { generateUuid } from 'vs/base/common/uuid';
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
suite('NotebookConcatDocument', function () {
@@ -30,6 +31,8 @@ suite('NotebookConcatDocument', function () {
let extHostDocumentsAndEditors: ExtHostDocumentsAndEditors;
let extHostDocuments: ExtHostDocuments;
let extHostNotebooks: ExtHostNotebookController;
let extHostNotebookDocuments: ExtHostNotebookDocuments;
const notebookUri = URI.parse('test:///notebook.file');
const disposables = new DisposableStore();
@@ -51,7 +54,9 @@ suite('NotebookConcatDocument', function () {
return URI.from({ scheme: 'test', path: generateUuid() });
}
};
extHostNotebooks = new ExtHostNotebookController(rpcProtocol, new ExtHostCommands(rpcProtocol, new NullLogService()), extHostDocumentsAndEditors, extHostDocuments, new NullLogService(), extHostStoragePaths);
extHostNotebooks = new ExtHostNotebookController(rpcProtocol, new ExtHostCommands(rpcProtocol, new NullLogService()), extHostDocumentsAndEditors, extHostDocuments, extHostStoragePaths);
extHostNotebookDocuments = new ExtHostNotebookDocuments(new NullLogService(), extHostNotebooks);
let reg = extHostNotebooks.registerNotebookContentProvider(nullExtensionDescription, 'test', new class extends mock<vscode.NotebookContentProvider>() {
// async openNotebook() { }
});
@@ -65,7 +70,7 @@ suite('NotebookConcatDocument', function () {
source: ['### Heading'],
eol: '\n',
language: 'markdown',
cellKind: CellKind.Markdown,
cellKind: CellKind.Markup,
outputs: [],
}],
versionId: 0
@@ -122,7 +127,7 @@ suite('NotebookConcatDocument', function () {
const cellUri1 = CellUri.generate(notebook.uri, 1);
const cellUri2 = CellUri.generate(notebook.uri, 2);
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
@@ -159,7 +164,7 @@ suite('NotebookConcatDocument', function () {
test('location, position mapping', function () {
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -204,7 +209,7 @@ suite('NotebookConcatDocument', function () {
let doc = new ExtHostNotebookConcatDocument(extHostNotebooks, extHostDocuments, notebook.apiNotebook, undefined);
// UPDATE 1
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -231,7 +236,7 @@ suite('NotebookConcatDocument', function () {
// UPDATE 2
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -259,7 +264,7 @@ suite('NotebookConcatDocument', function () {
assertLocation(doc, new Position(5, 12), new Location(notebook.apiNotebook.cellAt(1).document.uri, new Position(2, 11)), false); // don't check identity because position will be clamped
// UPDATE 3 (remove cell #2 again)
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -281,7 +286,7 @@ suite('NotebookConcatDocument', function () {
let doc = new ExtHostNotebookConcatDocument(extHostNotebooks, extHostDocuments, notebook.apiNotebook, undefined);
// UPDATE 1
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -340,7 +345,7 @@ suite('NotebookConcatDocument', function () {
test('selector', function () {
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -374,7 +379,7 @@ suite('NotebookConcatDocument', function () {
assertLines(fooLangDoc, 'fooLang-document');
assertLines(barLangDoc, 'barLang-document');
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -412,7 +417,7 @@ suite('NotebookConcatDocument', function () {
test('offsetAt(position) <-> positionAt(offset)', function () {
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -469,7 +474,7 @@ suite('NotebookConcatDocument', function () {
test('locationAt(position) <-> positionAt(location)', function () {
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -510,7 +515,7 @@ suite('NotebookConcatDocument', function () {
test('getText(range)', function () {
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -548,7 +553,7 @@ suite('NotebookConcatDocument', function () {
test('validateRange/Position', function () {
extHostNotebooks.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{

View File

@@ -1,6 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
@@ -8,18 +8,39 @@ import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
import { INotebookKernelDto2, MainContext, MainThreadCommandsShape, MainThreadNotebookKernelsShape } from 'vs/workbench/api/common/extHost.protocol';
import { INotebookKernelDto2, MainContext, MainThreadCommandsShape, MainThreadNotebookDocumentsShape, MainThreadNotebookKernelsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostNotebookKernels } from 'vs/workbench/api/common/extHostNotebookKernels';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { NullLogService } from 'vs/platform/log/common/log';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import { ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { CellKind, CellUri, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
suite('NotebookKernel', function () {
let rpcProtocol: TestRPCProtocol;
let extHostNotebookKernels: ExtHostNotebookKernels;
let notebook: ExtHostNotebookDocument;
let extHostDocumentsAndEditors: ExtHostDocumentsAndEditors;
let extHostDocuments: ExtHostDocuments;
let extHostNotebooks: ExtHostNotebookController;
let extHostNotebookDocuments: ExtHostNotebookDocuments;
const notebookUri = URI.parse('test:///notebook.file');
const kernelData = new Map<number, INotebookKernelDto2>();
const disposables = new DisposableStore();
teardown(function () {
disposables.clear();
});
setup(async function () {
kernelData.clear();
@@ -40,11 +61,67 @@ suite('NotebookKernel', function () {
kernelData.set(handle, { ...kernelData.get(handle)!, ...data, });
}
});
rpcProtocol.set(MainContext.MainThreadNotebookDocuments, new class extends mock<MainThreadNotebookDocumentsShape>() {
override async $applyEdits() { }
});
rpcProtocol.set(MainContext.MainThreadNotebook, new class extends mock<MainThreadNotebookShape>() {
override async $registerNotebookProvider() { }
override async $unregisterNotebookProvider() { }
});
extHostDocumentsAndEditors = new ExtHostDocumentsAndEditors(rpcProtocol, new NullLogService());
extHostDocuments = new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors);
const extHostStoragePaths = new class extends mock<IExtensionStoragePaths>() {
override workspaceValue() {
return URI.from({ scheme: 'test', path: generateUuid() });
}
};
extHostNotebooks = new ExtHostNotebookController(rpcProtocol, new ExtHostCommands(rpcProtocol, new NullLogService()), extHostDocumentsAndEditors, extHostDocuments, extHostStoragePaths);
extHostNotebookDocuments = new ExtHostNotebookDocuments(new NullLogService(), extHostNotebooks);
extHostNotebooks.$acceptDocumentAndEditorsDelta({
addedDocuments: [{
uri: notebookUri,
viewType: 'test',
versionId: 0,
cells: [{
handle: 0,
uri: CellUri.generate(notebookUri, 0),
source: ['### Heading'],
eol: '\n',
language: 'markdown',
cellKind: CellKind.Markup,
outputs: [],
}, {
handle: 1,
uri: CellUri.generate(notebookUri, 1),
source: ['console.log("aaa")', 'console.log("bbb")'],
eol: '\n',
language: 'javascript',
cellKind: CellKind.Code,
outputs: [],
}],
}],
addedEditors: [{
documentUri: notebookUri,
id: '_notebook_editor_0',
selections: [{ start: 0, end: 1 }],
visibleRanges: []
}]
});
extHostNotebooks.$acceptDocumentAndEditorsDelta({ newActiveEditor: '_notebook_editor_0' });
notebook = extHostNotebooks.notebookDocuments[0]!;
disposables.add(notebook);
disposables.add(extHostDocuments);
extHostNotebookKernels = new ExtHostNotebookKernels(
rpcProtocol,
new class extends mock<IExtHostInitDataService>() { },
new class extends mock<ExtHostNotebookController>() { }
extHostNotebooks,
new NullLogService()
);
});
@@ -53,12 +130,12 @@ suite('NotebookKernel', function () {
const kernel = extHostNotebookKernels.createNotebookController(nullExtensionDescription, 'foo', '*', 'Foo');
assert.throws(() => (<any>kernel).id = 'dd');
assert.throws(() => (<any>kernel).viewType = 'dd');
assert.throws(() => (<any>kernel).notebookType = 'dd');
assert.ok(kernel);
assert.strictEqual(kernel.id, 'foo');
assert.strictEqual(kernel.label, 'Foo');
assert.strictEqual(kernel.viewType, '*');
assert.strictEqual(kernel.notebookType, '*');
await rpcProtocol.sync();
assert.strictEqual(kernelData.size, 1);
@@ -67,7 +144,7 @@ suite('NotebookKernel', function () {
assert.strictEqual(first.id, 'nullExtensionDescription/foo');
assert.strictEqual(ExtensionIdentifier.equals(first.extensionId, nullExtensionDescription.identifier), true);
assert.strictEqual(first.label, 'Foo');
assert.strictEqual(first.viewType, '*');
assert.strictEqual(first.notebookType, '*');
kernel.dispose();
await rpcProtocol.sync();
@@ -93,4 +170,69 @@ suite('NotebookKernel', function () {
assert.strictEqual(first.id, 'nullExtensionDescription/foo');
assert.strictEqual(first.label, 'Far');
});
test('execute - simple createNotebookCellExecution', function () {
const kernel = extHostNotebookKernels.createNotebookController(nullExtensionDescription, 'foo', '*', 'Foo');
extHostNotebookKernels.$acceptNotebookAssociation(0, notebook.uri, true);
const cell1 = notebook.apiNotebook.cellAt(0);
const task = kernel.createNotebookCellExecution(cell1);
task.start();
task.end(undefined);
});
test('createNotebookCellExecution, must be selected/associated', function () {
const kernel = extHostNotebookKernels.createNotebookController(nullExtensionDescription, 'foo', '*', 'Foo');
assert.throws(() => {
kernel.createNotebookCellExecution(notebook.apiNotebook.cellAt(0));
});
extHostNotebookKernels.$acceptNotebookAssociation(0, notebook.uri, true);
kernel.createNotebookCellExecution(notebook.apiNotebook.cellAt(0));
});
test('createNotebookCellExecution, cell must be alive', function () {
const kernel = extHostNotebookKernels.createNotebookController(nullExtensionDescription, 'foo', '*', 'Foo');
const cell1 = notebook.apiNotebook.cellAt(0);
extHostNotebookKernels.$acceptNotebookAssociation(0, notebook.uri, true);
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
versionId: 12,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, notebook.apiNotebook.cellCount, []]]
}]
}, true);
assert.strictEqual(cell1.index, -1);
assert.throws(() => {
kernel.createNotebookCellExecution(cell1);
});
});
test('interrupt handler, cancellation', async function () {
let interruptCallCount = 0;
let tokenCancelCount = 0;
const kernel = extHostNotebookKernels.createNotebookController(nullExtensionDescription, 'foo', '*', 'Foo');
kernel.interruptHandler = () => { interruptCallCount += 1; };
extHostNotebookKernels.$acceptNotebookAssociation(0, notebook.uri, true);
const cell1 = notebook.apiNotebook.cellAt(0);
const task = kernel.createNotebookCellExecution(cell1);
task.token.onCancellationRequested(() => tokenCancelCount += 1);
await extHostNotebookKernels.$cancelCells(0, notebook.uri, [0]);
assert.strictEqual(interruptCallCount, 1);
assert.strictEqual(tokenCancelCount, 0);
await extHostNotebookKernels.$cancelCells(0, notebook.uri, [0]);
assert.strictEqual(interruptCallCount, 2);
assert.strictEqual(tokenCancelCount, 0);
});
});

View File

@@ -15,12 +15,12 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
import { MainThreadCommands } from 'vs/workbench/api/browser/mainThreadCommands';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { mock } from 'vs/base/test/common/mock';
import { TreeItemCollapsibleState, ITreeItem } from 'vs/workbench/common/views';
import { TreeItemCollapsibleState, ITreeItem, IRevealOptions } from 'vs/workbench/common/views';
import { NullLogService } from 'vs/platform/log/common/log';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import type { IDisposable } from 'vs/base/common/lifecycle';
suite.skip('ExtHostTreeView', function () {
suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
class RecordingShape extends mock<MainThreadTreeViewsShape>() {
@@ -35,7 +35,7 @@ suite.skip('ExtHostTreeView', function () {
});
}
override $reveal(): Promise<void> {
override $reveal(treeViewId: string, itemInfo: { item: ITreeItem, parentChain: ITreeItem[] } | undefined, options: IRevealOptions): Promise<void> {
return Promise.resolve();
}
@@ -515,8 +515,8 @@ suite.skip('ExtHostTreeView', function () {
.then(() => {
assert.ok(revealTarget.calledOnce);
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1]!.item));
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1]!.parentChain)).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
});
});
@@ -534,8 +534,8 @@ suite.skip('ExtHostTreeView', function () {
.then(() => {
assert.ok(revealTarget.calledOnce);
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1]!.item));
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1]!.parentChain)).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
}));
});
@@ -561,8 +561,8 @@ suite.skip('ExtHostTreeView', function () {
.then(() => {
assert.ok(revealTarget.calledOnce);
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1]!.item));
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1]!.parentChain)).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual({ select: false, focus: false, expand: false }, revealTarget.args[0][2]);
});
});
@@ -592,8 +592,8 @@ suite.skip('ExtHostTreeView', function () {
.then(() => {
assert.ok(revealTarget.calledOnce);
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1]!.item));
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1]!.parentChain)).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
});
});
@@ -633,8 +633,8 @@ suite.skip('ExtHostTreeView', function () {
.then(() => {
assert.ok(revealTarget.calledOnce);
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
assert.deepStrictEqual({ handle: '0/0:b/0:bc', label: { label: 'bc' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:b' }, removeUnsetKeys(revealTarget.args[0][1].item));
assert.deepStrictEqual([{ handle: '0/0:b', label: { label: 'b' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][1].parentChain).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual({ handle: '0/0:b/0:bc', label: { label: 'bc' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:b' }, removeUnsetKeys(revealTarget.args[0][1]!.item));
assert.deepStrictEqual([{ handle: '0/0:b', label: { label: 'b' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][1]!.parentChain).map(arg => removeUnsetKeys(arg)));
assert.deepStrictEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
});
});

View File

@@ -5,7 +5,8 @@
import * as assert from 'assert';
import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { MarkdownString, NotebookCellOutputItem, NotebookData } from 'vs/workbench/api/common/extHostTypeConverters';
import { isEmptyObject } from 'vs/base/common/types';
import { forEach } from 'vs/base/common/collections';
import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log';
@@ -81,4 +82,33 @@ suite('ExtHostTypeConverter', function () {
}
});
});
test('Notebook metadata is ignored when using Notebook Serializer #125716', function () {
const d = new extHostTypes.NotebookData([]);
d.cells.push(new extHostTypes.NotebookCellData(extHostTypes.NotebookCellKind.Code, 'hello', 'fooLang'));
d.metadata = { custom: { foo: 'bar', bar: 123 } };
const dto = NotebookData.from(d);
assert.strictEqual(dto.cells.length, 1);
assert.strictEqual(dto.cells[0].language, 'fooLang');
assert.strictEqual(dto.cells[0].source, 'hello');
assert.deepStrictEqual(dto.metadata, d.metadata);
});
test('NotebookCellOutputItem', function () {
const item = extHostTypes.NotebookCellOutputItem.text('Hello', 'foo/bar');
const dto = NotebookCellOutputItem.from(item);
assert.strictEqual(dto.mime, 'foo/bar');
assert.deepStrictEqual(dto.valueBytes, Array.from(new TextEncoder().encode('Hello')));
const item2 = NotebookCellOutputItem.to(dto);
assert.strictEqual(item2.mime, item.mime);
assert.deepStrictEqual(item2.data, item.data);
});
});

View File

@@ -8,7 +8,6 @@ import { URI } from 'vs/base/common/uri';
import * as types from 'vs/workbench/api/common/extHostTypes';
import { isWindows } from 'vs/base/common/platform';
import { assertType } from 'vs/base/common/types';
import { notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
function assertToJSON(a: any, expected: any) {
const raw = JSON.stringify(a);
@@ -649,57 +648,46 @@ suite('ExtHostTypes', function () {
assert.deepStrictEqual(md.value, '\n```html\n<img src=0 onerror="alert(1)">\n```\n');
});
test('NotebookMetadata - defaults', function () {
const obj = new types.NotebookDocumentMetadata();
assert.strictEqual(obj.trusted, notebookDocumentMetadataDefaults.trusted);
});
test('NotebookCellOutputItem - factories', function () {
test('NotebookMetadata - with', function () {
const obj = new types.NotebookDocumentMetadata();
const newObj = obj.with({ trusted: false });
assert.ok(obj !== newObj);
const sameObj = newObj.with({ trusted: false });
assert.ok(newObj === sameObj);
assert.strictEqual(obj.trusted, true);
assert.strictEqual(newObj.trusted, false);
});
assert.throws(() => {
// invalid mime type
new types.NotebookCellOutputItem(new Uint8Array(), 'invalid');
});
test('NotebookMetadata - with custom', function () {
const obj = new types.NotebookDocumentMetadata();
const newObj = obj.with({ trusted: false, mycustom: { display: 'hello' } });
assert.ok(obj !== newObj);
const sameObj = newObj.with({ trusted: false });
assert.ok(newObj === sameObj);
assert.strictEqual(obj.trusted, true);
assert.strictEqual(newObj.trusted, false);
assert.deepStrictEqual(newObj.mycustom, { display: 'hello' });
});
// --- err
test('NotebookCellMetadata - with', function () {
const obj = new types.NotebookCellMetadata(true, true);
let item = types.NotebookCellOutputItem.error(new Error());
assert.strictEqual(item.mime, 'application/vnd.code.notebook.error');
item = types.NotebookCellOutputItem.error({ name: 'Hello' });
assert.strictEqual(item.mime, 'application/vnd.code.notebook.error');
const newObj = obj.with({ inputCollapsed: false });
assert.ok(obj !== newObj);
assert.strictEqual(obj.inputCollapsed, true);
assert.strictEqual(obj.custom, undefined);
// --- JSON
assert.strictEqual(newObj.inputCollapsed, false);
assert.strictEqual(newObj.custom, undefined);
});
item = types.NotebookCellOutputItem.json(1);
assert.strictEqual(item.mime, 'application/json');
assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(1)));
test('NotebookCellMetadata - with custom', function () {
const obj = new types.NotebookCellMetadata(true, true);
const newObj = obj.with({ inputCollapsed: false, custom: { display: 'hello' } });
assert.ok(obj !== newObj);
const sameObj = newObj.with({ inputCollapsed: false });
assert.ok(newObj === sameObj);
assert.strictEqual(obj.inputCollapsed, true);
assert.strictEqual(newObj.inputCollapsed, false);
assert.deepStrictEqual(newObj.custom, { display: 'hello' });
item = types.NotebookCellOutputItem.json(1, 'foo/bar');
assert.strictEqual(item.mime, 'foo/bar');
assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(1)));
const newCustom = newObj.with({ anotherCustom: { display: 'hello2' } });
assert.strictEqual(newCustom.inputCollapsed, false);
assert.deepStrictEqual(newCustom.mycustom, undefined);
assert.deepStrictEqual(newCustom.anotherCustom, { display: 'hello2' });
item = types.NotebookCellOutputItem.json(true);
assert.strictEqual(item.mime, 'application/json');
assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(true)));
item = types.NotebookCellOutputItem.json([true, 1, 'ddd']);
assert.strictEqual(item.mime, 'application/json');
assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify([true, 1, 'ddd'], undefined, '\t')));
// --- text
item = types.NotebookCellOutputItem.text('Hęłlö');
assert.strictEqual(item.mime, 'text/plain');
assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö'));
item = types.NotebookCellOutputItem.text('Hęłlö', 'foo/bar');
assert.strictEqual(item.mime, 'foo/bar');
assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö'));
});
});

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { Schemas } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/base/test/common/mock';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
@@ -14,6 +15,7 @@ import { NullApiDeprecationService } from 'vs/workbench/api/common/extHostApiDep
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
import { ExtHostWebviewPanels } from 'vs/workbench/api/common/extHostWebviewPanels';
import { webviewResourceBaseHost } from 'vs/workbench/api/common/shared/webview';
import { EditorGroupColumn } from 'vs/workbench/common/editor';
import type * as vscode from 'vscode';
import { SingleProxyRPCProtocol } from './testRPCProtocol';
@@ -30,11 +32,7 @@ suite('ExtHostWebview', () => {
test('Cannot register multiple serializers for the same view type', async () => {
const viewType = 'view.type';
const extHostWebviews = new ExtHostWebviews(rpcProtocol!, {
webviewCspSource: '',
webviewResourceRoot: '',
isExtensionDevelopmentDebug: false,
}, undefined, new NullLogService(), NullApiDeprecationService);
const extHostWebviews = new ExtHostWebviews(rpcProtocol!, { remote: { authority: undefined, isRemote: false } }, undefined, new NullLogService(), NullApiDeprecationService);
const extHostWebviewPanels = new ExtHostWebviewPanels(rpcProtocol!, extHostWebviews, undefined);
@@ -78,95 +76,71 @@ suite('ExtHostWebview', () => {
assert.strictEqual(lastInvokedDeserializer, serializerB);
});
test('asWebviewUri for desktop vscode-resource scheme', () => {
const extHostWebviews = new ExtHostWebviews(rpcProtocol!, {
webviewCspSource: '',
webviewResourceRoot: 'vscode-resource://{{resource}}',
isExtensionDevelopmentDebug: false,
}, undefined, new NullLogService(), NullApiDeprecationService);
const extHostWebviewPanels = new ExtHostWebviewPanels(rpcProtocol!, extHostWebviews, undefined);
const webview = extHostWebviewPanels.createWebviewPanel({} as any, 'type', 'title', 1, {});
test('asWebviewUri for local file paths', () => {
const webview = createWebview(rpcProtocol, /* remoteAuthority */undefined);
assert.strictEqual(
webview.webview.asWebviewUri(URI.parse('file:///Users/codey/file.html')).toString(),
'vscode-resource://file///Users/codey/file.html',
(webview.webview.asWebviewUri(URI.parse('file:///Users/codey/file.html')).toString()),
`https://file%2B.vscode-resource.${webviewResourceBaseHost}/Users/codey/file.html`,
'Unix basic'
);
assert.strictEqual(
webview.webview.asWebviewUri(URI.parse('file:///Users/codey/file.html#frag')).toString(),
'vscode-resource://file///Users/codey/file.html#frag',
(webview.webview.asWebviewUri(URI.parse('file:///Users/codey/file.html#frag')).toString()),
`https://file%2B.vscode-resource.${webviewResourceBaseHost}/Users/codey/file.html#frag`,
'Unix should preserve fragment'
);
assert.strictEqual(
webview.webview.asWebviewUri(URI.parse('file:///Users/codey/f%20ile.html')).toString(),
'vscode-resource://file///Users/codey/f%20ile.html',
(webview.webview.asWebviewUri(URI.parse('file:///Users/codey/f%20ile.html')).toString()),
`https://file%2B.vscode-resource.${webviewResourceBaseHost}/Users/codey/f%20ile.html`,
'Unix with encoding'
);
assert.strictEqual(
webview.webview.asWebviewUri(URI.parse('file://localhost/Users/codey/file.html')).toString(),
'vscode-resource://file//localhost/Users/codey/file.html',
(webview.webview.asWebviewUri(URI.parse('file://localhost/Users/codey/file.html')).toString()),
`https://file%2Blocalhost.vscode-resource.${webviewResourceBaseHost}/Users/codey/file.html`,
'Unix should preserve authority'
);
assert.strictEqual(
webview.webview.asWebviewUri(URI.parse('file:///c:/codey/file.txt')).toString(),
'vscode-resource://file///c%3A/codey/file.txt',
(webview.webview.asWebviewUri(URI.parse('file:///c:/codey/file.txt')).toString()),
`https://file%2B.vscode-resource.${webviewResourceBaseHost}/c%3A/codey/file.txt`,
'Windows C drive'
);
});
test('asWebviewUri for web endpoint', () => {
const extHostWebviews = new ExtHostWebviews(rpcProtocol!, {
webviewCspSource: '',
webviewResourceRoot: `https://{{uuid}}.webview.contoso.com/commit/{{resource}}`,
isExtensionDevelopmentDebug: false,
}, undefined, new NullLogService(), NullApiDeprecationService);
const extHostWebviewPanels = new ExtHostWebviewPanels(rpcProtocol!, extHostWebviews, undefined);
const webview = extHostWebviewPanels.createWebviewPanel({} as any, 'type', 'title', 1, {});
function stripEndpointUuid(input: string) {
return input.replace(/^https:\/\/[^\.]+?\./, '');
}
test('asWebviewUri for remote file paths', () => {
const webview = createWebview(rpcProtocol, /* remoteAuthority */ 'remote');
assert.strictEqual(
stripEndpointUuid(webview.webview.asWebviewUri(URI.parse('file:///Users/codey/file.html')).toString()),
'webview.contoso.com/commit/file///Users/codey/file.html',
(webview.webview.asWebviewUri(URI.parse('file:///Users/codey/file.html')).toString()),
`https://vscode-remote%2Bremote.vscode-resource.${webviewResourceBaseHost}/Users/codey/file.html`,
'Unix basic'
);
assert.strictEqual(
stripEndpointUuid(webview.webview.asWebviewUri(URI.parse('file:///Users/codey/file.html#frag')).toString()),
'webview.contoso.com/commit/file///Users/codey/file.html#frag',
'Unix should preserve fragment'
);
assert.strictEqual(
stripEndpointUuid(webview.webview.asWebviewUri(URI.parse('file:///Users/codey/f%20ile.html')).toString()),
'webview.contoso.com/commit/file///Users/codey/f%20ile.html',
'Unix with encoding'
);
assert.strictEqual(
stripEndpointUuid(webview.webview.asWebviewUri(URI.parse('file://localhost/Users/codey/file.html')).toString()),
'webview.contoso.com/commit/file//localhost/Users/codey/file.html',
'Unix should preserve authority'
);
assert.strictEqual(
stripEndpointUuid(webview.webview.asWebviewUri(URI.parse('file:///c:/codey/file.txt')).toString()),
'webview.contoso.com/commit/file///c%3A/codey/file.txt',
'Windows C drive'
);
});
});
function createWebview(rpcProtocol: (IExtHostRpcService & IExtHostContext) | undefined, remoteAuthority: string | undefined) {
const extHostWebviews = new ExtHostWebviews(rpcProtocol!, {
remote: {
authority: remoteAuthority,
isRemote: !!remoteAuthority,
},
}, undefined, new NullLogService(), NullApiDeprecationService);
const extHostWebviewPanels = new ExtHostWebviewPanels(rpcProtocol!, extHostWebviews, undefined);
const webview = extHostWebviewPanels.createWebviewPanel({
extensionLocation: URI.from({
scheme: remoteAuthority ? Schemas.vscodeRemote : Schemas.file,
authority: remoteAuthority,
path: '/ext/path',
})
} as IExtensionDescription, 'type', 'title', 1, {});
return webview;
}
function createNoopMainThreadWebviews() {
return new class extends mock<MainThreadWebviewManager>() {

View File

@@ -0,0 +1,75 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
suite('Diff editor input', () => {
class MyEditorInput extends EditorInput {
readonly resource = undefined;
override get typeId(): string { return 'myEditorInput'; }
override resolve(): any { return null; }
}
test('basics', () => {
const instantiationService = workbenchInstantiationService();
let counter = 0;
let input = new MyEditorInput();
input.onWillDispose(() => {
assert(true);
counter++;
});
let otherInput = new MyEditorInput();
otherInput.onWillDispose(() => {
assert(true);
counter++;
});
let diffInput = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input, otherInput, undefined);
assert.strictEqual(diffInput.originalInput, input);
assert.strictEqual(diffInput.modifiedInput, otherInput);
assert(diffInput.matches(diffInput));
assert(!diffInput.matches(otherInput));
assert(!diffInput.matches(null));
diffInput.dispose();
assert.strictEqual(counter, 0);
});
test('disposes when input inside disposes', function () {
const instantiationService = workbenchInstantiationService();
let counter = 0;
let input = new MyEditorInput();
let otherInput = new MyEditorInput();
let diffInput = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input, otherInput, undefined);
diffInput.onWillDispose(() => {
counter++;
assert(true);
});
input.dispose();
input = new MyEditorInput();
otherInput = new MyEditorInput();
let diffInput2 = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input, otherInput, undefined);
diffInput2.onWillDispose(() => {
counter++;
assert(true);
});
otherInput.dispose();
assert.strictEqual(counter, 2);
});
});

View File

@@ -4,15 +4,23 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource } from 'vs/workbench/common/editor';
import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, EditorInputCapabilities, isEditorIdentifier } 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';
import { workbenchInstantiationService, TestServiceAccessor, TestEditorInput } from 'vs/workbench/test/browser/workbenchTestServices';
import { workbenchInstantiationService, TestServiceAccessor, TestEditorInput, registerTestEditor, registerTestFileEditor, registerTestResourceEditor, TestFileEditorInput, createEditorPart, registerTestSideBySideEditor } from 'vs/workbench/test/browser/workbenchTestServices';
import { Schemas } from 'vs/base/common/network';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { toResource } from 'vs/base/test/common/utils';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { whenEditorClosed } from 'vs/workbench/browser/editor';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
suite('Workbench editor', () => {
suite('Workbench editor utils', () => {
class TestEditorInputWithPreferredResource extends TestEditorInput implements IEditorInputWithPreferredResource {
@@ -21,16 +29,93 @@ suite('Workbench editor', () => {
}
}
const disposables = new DisposableStore();
const TEST_EDITOR_ID = 'MyTestEditorForEditors';
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
async function createServices(): Promise<TestServiceAccessor> {
const instantiationService = workbenchInstantiationService();
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
const editorService = instantiationService.createInstance(EditorService);
instantiationService.stub(IEditorService, editorService);
return instantiationService.createInstance(TestServiceAccessor);
}
setup(() => {
instantiationService = workbenchInstantiationService();
accessor = instantiationService.createInstance(TestServiceAccessor);
disposables.add(registerTestFileEditor());
disposables.add(registerTestSideBySideEditor());
disposables.add(registerTestResourceEditor());
disposables.add(registerTestEditor(TEST_EDITOR_ID, [new SyncDescriptor(TestFileEditorInput)]));
});
teardown(() => {
accessor.untitledTextEditorService.dispose();
disposables.clear();
});
test('EditorInputCapabilities', () => {
const testInput1 = new TestFileEditorInput(URI.file('resource1'), 'testTypeId');
const testInput2 = new TestFileEditorInput(URI.file('resource2'), 'testTypeId');
testInput1.capabilities = EditorInputCapabilities.None;
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.None), true);
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Readonly), false);
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Untitled), false);
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.RequiresTrust), false);
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Singleton), false);
testInput1.capabilities |= EditorInputCapabilities.Readonly;
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Readonly), true);
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.None), false);
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Untitled), false);
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.RequiresTrust), false);
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Singleton), false);
testInput1.capabilities = EditorInputCapabilities.None;
testInput2.capabilities = EditorInputCapabilities.None;
const sideBySideInput = new SideBySideEditorInput('name', undefined, testInput1, testInput2);
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.None), true);
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Readonly), false);
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Untitled), false);
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.RequiresTrust), false);
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Singleton), false);
testInput1.capabilities |= EditorInputCapabilities.Readonly;
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Readonly), false);
testInput2.capabilities |= EditorInputCapabilities.Readonly;
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Readonly), true);
testInput1.capabilities |= EditorInputCapabilities.Untitled;
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Untitled), false);
testInput2.capabilities |= EditorInputCapabilities.Untitled;
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Untitled), true);
testInput1.capabilities |= EditorInputCapabilities.RequiresTrust;
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.RequiresTrust), true);
testInput2.capabilities |= EditorInputCapabilities.RequiresTrust;
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.RequiresTrust), true);
testInput1.capabilities |= EditorInputCapabilities.Singleton;
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Singleton), true);
testInput2.capabilities |= EditorInputCapabilities.Singleton;
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Singleton), true);
});
test('EditorResourceAccessor', () => {
@@ -123,4 +208,57 @@ suite('Workbench editor', () => {
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(fileWithPreferredResource)?.toString(), resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(fileWithPreferredResource)?.toString(), preferredResource.toString());
});
test('isEditorIdentifier', () => {
assert.strictEqual(isEditorIdentifier(undefined), false);
assert.strictEqual(isEditorIdentifier('undefined'), false);
const testInput1 = new TestFileEditorInput(URI.file('resource1'), 'testTypeId');
assert.strictEqual(isEditorIdentifier(testInput1), false);
assert.strictEqual(isEditorIdentifier({ editor: testInput1, groupId: 3 }), true);
});
test('whenEditorClosed (single editor)', async function () {
return testWhenEditorClosed(false, false, toResource.call(this, '/path/index.txt'));
});
test('whenEditorClosed (multiple editor)', async function () {
return testWhenEditorClosed(false, false, toResource.call(this, '/path/index.txt'), toResource.call(this, '/test.html'));
});
test('whenEditorClosed (single editor, diff editor)', async function () {
return testWhenEditorClosed(true, false, toResource.call(this, '/path/index.txt'));
});
test('whenEditorClosed (multiple editor, diff editor)', async function () {
return testWhenEditorClosed(true, false, toResource.call(this, '/path/index.txt'), toResource.call(this, '/test.html'));
});
test('whenEditorClosed (single custom editor)', async function () {
return testWhenEditorClosed(false, true, toResource.call(this, '/path/index.txt'));
});
test('whenEditorClosed (multiple custom editor)', async function () {
return testWhenEditorClosed(false, true, toResource.call(this, '/path/index.txt'), toResource.call(this, '/test.html'));
});
async function testWhenEditorClosed(sideBySide: boolean, custom: boolean, ...resources: URI[]): Promise<void> {
const accessor = await createServices();
for (const resource of resources) {
if (custom) {
await accessor.editorService.openEditor(new TestFileEditorInput(resource, 'testTypeId'), { pinned: true });
} else if (sideBySide) {
await accessor.editorService.openEditor(new SideBySideEditorInput('testSideBySideEditor', undefined, new TestFileEditorInput(resource, 'testTypeId'), new TestFileEditorInput(resource, 'testTypeId')), { pinned: true });
} else {
await accessor.editorService.openEditor({ resource, options: { pinned: true } });
}
}
const closedPromise = accessor.instantitionService.invokeFunction(accessor => whenEditorClosed(accessor, resources));
accessor.editorGroupService.activeGroup.closeAllEditors();
await closedPromise;
}
});

View File

@@ -6,13 +6,13 @@
import * as assert from 'assert';
import { TextDiffEditorModel } from 'vs/workbench/common/editor/textDiffEditorModel';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput';
import { URI } from 'vs/base/common/uri';
import { workbenchInstantiationService, TestServiceAccessor } from 'vs/workbench/test/browser/workbenchTestServices';
import { ITextModel } from 'vs/editor/common/model';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
suite('Workbench editor model', () => {
suite('TextDiffEditorModel', () => {
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
@@ -22,7 +22,7 @@ suite('Workbench editor model', () => {
accessor = instantiationService.createInstance(TestServiceAccessor);
});
test('TextDiffEditorModel', async () => {
test('basics', async () => {
const dispose = accessor.textModelResolverService.registerTextModelContentProvider('test', {
provideTextContent: async function (resource: URI): Promise<ITextModel | null> {
if (resource.scheme === 'test') {
@@ -36,8 +36,8 @@ suite('Workbench editor model', () => {
}
});
let input = instantiationService.createInstance(ResourceEditorInput, URI.from({ scheme: 'test', authority: null!, path: 'thePath' }), 'name', 'description', undefined);
let otherInput = instantiationService.createInstance(ResourceEditorInput, URI.from({ scheme: 'test', authority: null!, path: 'thePath' }), 'name2', 'description', undefined);
let input = instantiationService.createInstance(TextResourceEditorInput, URI.from({ scheme: 'test', authority: null!, path: 'thePath' }), 'name', 'description', undefined, undefined);
let otherInput = instantiationService.createInstance(TextResourceEditorInput, URI.from({ scheme: 'test', authority: null!, path: 'thePath' }), 'name2', 'description', undefined, undefined);
let diffInput = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input, otherInput, undefined);
let model = await diffInput.resolve() as TextDiffEditorModel;

View File

@@ -5,7 +5,7 @@
import * as assert from 'assert';
import { EditorGroupModel, ISerializedEditorGroupModel, EditorCloseEvent } from 'vs/workbench/common/editor/editorGroupModel';
import { EditorExtensions, IEditorInputFactoryRegistry, EditorInput, IFileEditorInput, IEditorInputSerializer, CloseDirection, EditorsOrder } from 'vs/workbench/common/editor';
import { EditorExtensions, IEditorInputFactoryRegistry, IFileEditorInput, IEditorInputSerializer, CloseDirection, EditorsOrder } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';
import { TestLifecycleService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
@@ -22,8 +22,9 @@ import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { TestContextService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
suite('Workbench editor group model', () => {
suite('EditorGroupModel', () => {
function inst(): IInstantiationService {
let inst = new TestInstantiationService();
@@ -166,6 +167,7 @@ suite('Workbench editor group model', () => {
getEncoding() { return undefined; }
setPreferredEncoding(encoding: string) { }
setForceOpenAsBinary(): void { }
setPreferredContents(contents: string): void { }
setMode(mode: string) { }
setPreferredMode(mode: string) { }
isResolved(): boolean { return false; }
@@ -256,7 +258,7 @@ suite('Workbench editor group model', () => {
assert.strictEqual(clone.count, 3);
let didEditorLabelChange = false;
const toDispose = clone.onDidEditorLabelChange(() => didEditorLabelChange = true);
const toDispose = clone.onDidChangeEditorLabel(() => didEditorLabelChange = true);
input1.setLabel();
assert.ok(didEditorLabelChange);
@@ -1558,12 +1560,12 @@ suite('Workbench editor group model', () => {
});
let label1ChangeCounter = 0;
group1.onDidEditorLabelChange(() => {
group1.onDidChangeEditorLabel(() => {
label1ChangeCounter++;
});
let label2ChangeCounter = 0;
group2.onDidEditorLabelChange(() => {
group2.onDidChangeEditorLabel(() => {
label2ChangeCounter++;
});

View File

@@ -4,11 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { EditorInput } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
suite('Workbench editor input', () => {
suite('EditorInput', () => {
class MyEditorInput extends EditorInput {
readonly resource = undefined;
@@ -17,7 +15,7 @@ suite('Workbench editor input', () => {
override resolve(): any { return null; }
}
test('EditorInput', () => {
test('basics', () => {
let counter = 0;
let input = new MyEditorInput();
let otherInput = new MyEditorInput();
@@ -35,60 +33,4 @@ suite('Workbench editor input', () => {
input.dispose();
assert.strictEqual(counter, 1);
});
test('DiffEditorInput', () => {
const instantiationService = workbenchInstantiationService();
let counter = 0;
let input = new MyEditorInput();
input.onWillDispose(() => {
assert(true);
counter++;
});
let otherInput = new MyEditorInput();
otherInput.onWillDispose(() => {
assert(true);
counter++;
});
let diffInput = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input, otherInput, undefined);
assert.strictEqual(diffInput.originalInput, input);
assert.strictEqual(diffInput.modifiedInput, otherInput);
assert(diffInput.matches(diffInput));
assert(!diffInput.matches(otherInput));
assert(!diffInput.matches(null));
diffInput.dispose();
assert.strictEqual(counter, 0);
});
test('DiffEditorInput disposes when input inside disposes', function () {
const instantiationService = workbenchInstantiationService();
let counter = 0;
let input = new MyEditorInput();
let otherInput = new MyEditorInput();
let diffInput = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input, otherInput, undefined);
diffInput.onWillDispose(() => {
counter++;
assert(true);
});
input.dispose();
input = new MyEditorInput();
otherInput = new MyEditorInput();
let diffInput2 = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input, otherInput, undefined);
diffInput2.onWillDispose(() => {
counter++;
assert(true);
});
otherInput.dispose();
assert.strictEqual(counter, 2);
});
});

View File

@@ -5,7 +5,6 @@
import * as assert from 'assert';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { EditorModel } from 'vs/workbench/common/editor';
import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
@@ -26,8 +25,9 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { TestTextResourcePropertiesService } from 'vs/workbench/test/common/workbenchTestServices';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { EditorModel } from 'vs/workbench/common/editor/editorModel';
suite('Workbench editor model', () => {
suite('EditorModel', () => {
class MyEditorModel extends EditorModel { }
class MyTextEditorModel extends BaseTextEditorModel {
@@ -62,7 +62,7 @@ suite('Workbench editor model', () => {
modeService = instantiationService.stub(IModeService, ModeServiceImpl);
});
test('EditorModel', async () => {
test('basics', async () => {
let counter = 0;
const model = new MyEditorModel();

View File

@@ -5,27 +5,34 @@
import * as assert from 'assert';
import { EditorPane, EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane';
import { EditorInput, EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor';
import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor';
import { 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';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { workbenchInstantiationService, TestEditorGroupView, TestEditorGroupsService, registerTestResourceEditor, TestEditorInput } from 'vs/workbench/test/browser/workbenchTestServices';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { workbenchInstantiationService, TestEditorGroupView, TestEditorGroupsService, registerTestResourceEditor, TestEditorInput, createEditorPart } from 'vs/workbench/test/browser/workbenchTestServices';
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';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { extUri } from 'vs/base/common/resources';
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { TestWorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
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 {
@@ -69,8 +76,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 {
@@ -94,90 +101,90 @@ class OtherTestInput extends EditorInput {
return null;
}
}
class TestResourceEditorInput extends ResourceEditorInput { }
class TestResourceEditorInput extends TextResourceEditorInput { }
suite('Workbench EditorPane', () => {
suite('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 = {};
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, undefined))!.instantiate(inst);
assert.strictEqual(editor.getId(), 'testEditor');
const otherEditor = EditorRegistry.getEditor(inst.createInstance(ResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst);
const otherEditor = editorRegistry.getEditor(inst.createInstance(TextResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, 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, undefined))!.instantiate(inst);
assert.strictEqual('workbench.editors.textResourceEditor', editor.getId());
@@ -186,17 +193,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();
});
@@ -277,7 +284,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 });
@@ -320,7 +327,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'));
@@ -358,7 +365,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'));
@@ -393,4 +400,72 @@ suite('Workbench EditorPane', () => {
res = memento.loadEditorState(testGroup0, testInputB);
assert.ok(!res);
});
test('WorkspaceTrustRequiredEditor', async function () {
class TrustRequiredTestEditor extends EditorPane {
constructor(@ITelemetryService telemetryService: ITelemetryService) {
super('TestEditor', NullTelemetryService, NullThemeService, new TestStorageService());
}
override getId(): string { return 'trustRequiredTestEditor'; }
layout(): void { }
createEditor(): any { }
}
class TrustRequiredTestInput extends EditorInput {
readonly resource = undefined;
override get typeId(): string {
return 'trustRequiredTestInput';
}
override get capabilities(): EditorInputCapabilities {
return EditorInputCapabilities.RequiresTrust;
}
override resolve(): any {
return null;
}
}
const disposables = new DisposableStore();
const instantiationService = workbenchInstantiationService();
const workspaceTrustService = instantiationService.createInstance(TestWorkspaceTrustManagementService);
instantiationService.stub(IWorkspaceTrustManagementService, workspaceTrustService);
workspaceTrustService.setWorkspaceTrust(false);
const editorPart = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, editorPart);
const editorService = instantiationService.createInstance(EditorService);
instantiationService.stub(IEditorService, editorService);
const group = editorPart.activeGroup;
const editorDescriptor = EditorDescriptor.create(TrustRequiredTestEditor, 'id1', 'name');
disposables.add(editorRegistry.registerEditor(editorDescriptor, [new SyncDescriptor(TrustRequiredTestInput)]));
const testInput = new TrustRequiredTestInput();
await group.openEditor(testInput);
assert.strictEqual(group.activeEditorPane?.getId(), WorkspaceTrustRequiredEditor.ID);
const getEditorPaneIdAsync = () => new Promise(resolve => {
disposables.add(editorService.onDidActiveEditorChange(event => {
resolve(group.activeEditorPane?.getId());
}));
});
workspaceTrustService.setWorkspaceTrust(true);
assert.strictEqual(await getEditorPaneIdAsync(), 'trustRequiredTestEditor');
workspaceTrustService.setWorkspaceTrust(false);
assert.strictEqual(await getEditorPaneIdAsync(), WorkspaceTrustRequiredEditor.ID);
dispose(disposables);
});
});

View File

@@ -5,50 +5,51 @@
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { workbenchInstantiationService, TestServiceAccessor } from 'vs/workbench/test/browser/workbenchTestServices';
import { snapshotToString } from 'vs/workbench/services/textfile/common/textfiles';
import { ModesRegistry, PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { AbstractResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { ILabelService } from 'vs/platform/label/common/label';
import { IFileService } from 'vs/platform/files/common/files';
import { EditorInputCapabilities, Verbosity } from 'vs/workbench/common/editor';
suite('Resource text editors', () => {
suite('ResourceEditorInput', () => {
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
class TestResourceEditorInput extends AbstractResourceEditorInput {
readonly typeId = 'test.typeId';
constructor(
resource: URI,
@ILabelService labelService: ILabelService,
@IFileService fileService: IFileService
) {
super(resource, resource, labelService, fileService);
}
}
setup(() => {
instantiationService = workbenchInstantiationService();
accessor = instantiationService.createInstance(TestServiceAccessor);
});
test('basics', async () => {
const resource = URI.from({ scheme: 'inmemory', authority: null!, path: 'thePath' });
accessor.modelService.createModel('function test() {}', accessor.modeService.create('text'), resource);
const resource = URI.from({ scheme: 'testResource', path: 'thePath/of/the/resource.txt' });
const input: ResourceEditorInput = instantiationService.createInstance(ResourceEditorInput, resource, 'The Name', 'The Description', undefined);
const input = instantiationService.createInstance(TestResourceEditorInput, resource);
const model = await input.resolve();
assert.ok(input.getName().length > 0);
assert.ok(model);
assert.strictEqual(snapshotToString(((model as ResourceEditorModel).createSnapshot()!)), 'function test() {}');
});
assert.ok(input.getDescription(Verbosity.SHORT)!.length > 0);
assert.ok(input.getDescription(Verbosity.MEDIUM)!.length > 0);
assert.ok(input.getDescription(Verbosity.LONG)!.length > 0);
test('custom mode', async () => {
ModesRegistry.registerLanguage({
id: 'resource-input-test',
});
assert.ok(input.getTitle(Verbosity.SHORT).length > 0);
assert.ok(input.getTitle(Verbosity.MEDIUM).length > 0);
assert.ok(input.getTitle(Verbosity.LONG).length > 0);
const resource = URI.from({ scheme: 'inmemory', authority: null!, path: 'thePath' });
accessor.modelService.createModel('function test() {}', accessor.modeService.create('text'), resource);
const input: ResourceEditorInput = instantiationService.createInstance(ResourceEditorInput, resource, 'The Name', 'The Description', 'resource-input-test');
const model = await input.resolve();
assert.ok(model);
assert.strictEqual(model.textEditorModel?.getModeId(), 'resource-input-test');
input.setMode('text');
assert.strictEqual(model.textEditorModel?.getModeId(), PLAINTEXT_MODE_ID);
assert.strictEqual(input.hasCapability(EditorInputCapabilities.Readonly), false);
assert.strictEqual(input.hasCapability(EditorInputCapabilities.Untitled), true);
assert.strictEqual(input.isOrphaned(), false);
});
});

View File

@@ -0,0 +1,61 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
suite('SideBySideEditorInput', () => {
class MyEditorInput extends EditorInput {
readonly resource = undefined;
override get typeId(): string { return 'myEditorInput'; }
override resolve(): any { return null; }
fireCapabilitiesChangeEvent(): void {
this._onDidChangeCapabilities.fire();
}
fireDirtyChangeEvent(): void {
this._onDidChangeDirty.fire();
}
fireLabelChangeEvent(): void {
this._onDidChangeLabel.fire();
}
}
test('events dispatching', () => {
let input = new MyEditorInput();
let otherInput = new MyEditorInput();
const sideBySideInut = new SideBySideEditorInput('name', 'description', otherInput, input);
let capabilitiesChangeCounter = 0;
sideBySideInut.onDidChangeCapabilities(() => capabilitiesChangeCounter++);
let dirtyChangeCounter = 0;
sideBySideInut.onDidChangeDirty(() => dirtyChangeCounter++);
let labelChangeCounter = 0;
sideBySideInut.onDidChangeLabel(() => labelChangeCounter++);
input.fireCapabilitiesChangeEvent();
assert.strictEqual(capabilitiesChangeCounter, 1);
otherInput.fireCapabilitiesChangeEvent();
assert.strictEqual(capabilitiesChangeCounter, 2);
input.fireDirtyChangeEvent();
otherInput.fireDirtyChangeEvent();
assert.strictEqual(dirtyChangeCounter, 1);
input.fireLabelChangeEvent();
otherInput.fireLabelChangeEvent();
assert.strictEqual(labelChangeCounter, 1);
});
});

View File

@@ -0,0 +1,108 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput';
import { TextResourceEditorModel } from 'vs/workbench/common/editor/textResourceEditorModel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { workbenchInstantiationService, TestServiceAccessor } from 'vs/workbench/test/browser/workbenchTestServices';
import { snapshotToString } from 'vs/workbench/services/textfile/common/textfiles';
import { ModesRegistry, PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
suite('TextResourceEditorInput', () => {
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
setup(() => {
instantiationService = workbenchInstantiationService();
accessor = instantiationService.createInstance(TestServiceAccessor);
});
test('basics', async () => {
const resource = URI.from({ scheme: 'inmemory', authority: null!, path: 'thePath' });
accessor.modelService.createModel('function test() {}', accessor.modeService.create('text'), resource);
const input = instantiationService.createInstance(TextResourceEditorInput, resource, 'The Name', 'The Description', undefined, undefined);
const model = await input.resolve();
assert.ok(model);
assert.strictEqual(snapshotToString(((model as TextResourceEditorModel).createSnapshot()!)), 'function test() {}');
});
test('preferred mode (via ctor)', async () => {
ModesRegistry.registerLanguage({
id: 'resource-input-test',
});
const resource = URI.from({ scheme: 'inmemory', authority: null!, path: 'thePath' });
accessor.modelService.createModel('function test() {}', accessor.modeService.create('text'), resource);
const input = instantiationService.createInstance(TextResourceEditorInput, resource, 'The Name', 'The Description', 'resource-input-test', undefined);
const model = await input.resolve();
assert.ok(model);
assert.strictEqual(model.textEditorModel?.getModeId(), 'resource-input-test');
input.setMode('text');
assert.strictEqual(model.textEditorModel?.getModeId(), PLAINTEXT_MODE_ID);
await input.resolve();
assert.strictEqual(model.textEditorModel?.getModeId(), PLAINTEXT_MODE_ID);
});
test('preferred mode (via setPreferredMode)', async () => {
ModesRegistry.registerLanguage({
id: 'resource-input-test',
});
const resource = URI.from({ scheme: 'inmemory', authority: null!, path: 'thePath' });
accessor.modelService.createModel('function test() {}', accessor.modeService.create('text'), resource);
const input = instantiationService.createInstance(TextResourceEditorInput, resource, 'The Name', 'The Description', undefined, undefined);
input.setPreferredMode('resource-input-test');
const model = await input.resolve();
assert.ok(model);
assert.strictEqual(model.textEditorModel?.getModeId(), 'resource-input-test');
});
test('preferred contents (via ctor)', async () => {
const resource = URI.from({ scheme: 'inmemory', authority: null!, path: 'thePath' });
accessor.modelService.createModel('function test() {}', accessor.modeService.create('text'), resource);
const input = instantiationService.createInstance(TextResourceEditorInput, resource, 'The Name', 'The Description', undefined, 'My Resource Input Contents');
const model = await input.resolve();
assert.ok(model);
assert.strictEqual(model.textEditorModel?.getValue(), 'My Resource Input Contents');
model.textEditorModel.setValue('Some other contents');
assert.strictEqual(model.textEditorModel?.getValue(), 'Some other contents');
await input.resolve();
assert.strictEqual(model.textEditorModel?.getValue(), 'Some other contents'); // preferred contents only used once
});
test('preferred contents (via setPreferredContents)', async () => {
const resource = URI.from({ scheme: 'inmemory', authority: null!, path: 'thePath' });
accessor.modelService.createModel('function test() {}', accessor.modeService.create('text'), resource);
const input = instantiationService.createInstance(TextResourceEditorInput, resource, 'The Name', 'The Description', undefined, undefined);
input.setPreferredContents('My Resource Input Contents');
const model = await input.resolve();
assert.ok(model);
assert.strictEqual(model.textEditorModel?.getValue(), 'My Resource Input Contents');
model.textEditorModel.setValue('Some other contents');
assert.strictEqual(model.textEditorModel?.getValue(), 'Some other contents');
await input.resolve();
assert.strictEqual(model.textEditorModel?.getValue(), 'Some other contents'); // preferred contents only used once
});
});

View File

@@ -0,0 +1,331 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { Registry } from 'vs/platform/registry/common/platform';
import { IQuickAccessRegistry, Extensions, IQuickAccessProvider, QuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
import { IQuickPick, IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { TestServiceAccessor, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { DisposableStore, toDisposable, IDisposable } from 'vs/base/common/lifecycle';
import { timeout } from 'vs/base/common/async';
import { PickerQuickAccessProvider, FastAndSlowPicks } from 'vs/platform/quickinput/browser/pickerQuickAccess';
suite('QuickAccess', () => {
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
let providerDefaultCalled = false;
let providerDefaultCanceled = false;
let providerDefaultDisposed = false;
let provider1Called = false;
let provider1Canceled = false;
let provider1Disposed = false;
let provider2Called = false;
let provider2Canceled = false;
let provider2Disposed = false;
let provider3Called = false;
let provider3Canceled = false;
let provider3Disposed = false;
class TestProviderDefault implements IQuickAccessProvider {
constructor(@IQuickInputService private readonly quickInputService: IQuickInputService, disposables: DisposableStore) { }
provide(picker: IQuickPick<IQuickPickItem>, token: CancellationToken): IDisposable {
assert.ok(picker);
providerDefaultCalled = true;
token.onCancellationRequested(() => providerDefaultCanceled = true);
// bring up provider #3
setTimeout(() => this.quickInputService.quickAccess.show(providerDescriptor3.prefix));
return toDisposable(() => providerDefaultDisposed = true);
}
}
class TestProvider1 implements IQuickAccessProvider {
provide(picker: IQuickPick<IQuickPickItem>, token: CancellationToken): IDisposable {
assert.ok(picker);
provider1Called = true;
token.onCancellationRequested(() => provider1Canceled = true);
return toDisposable(() => provider1Disposed = true);
}
}
class TestProvider2 implements IQuickAccessProvider {
provide(picker: IQuickPick<IQuickPickItem>, token: CancellationToken): IDisposable {
assert.ok(picker);
provider2Called = true;
token.onCancellationRequested(() => provider2Canceled = true);
return toDisposable(() => provider2Disposed = true);
}
}
class TestProvider3 implements IQuickAccessProvider {
provide(picker: IQuickPick<IQuickPickItem>, token: CancellationToken): IDisposable {
assert.ok(picker);
provider3Called = true;
token.onCancellationRequested(() => provider3Canceled = true);
// hide without picking
setTimeout(() => picker.hide());
return toDisposable(() => provider3Disposed = true);
}
}
const providerDescriptorDefault = { ctor: TestProviderDefault, prefix: '', helpEntries: [] };
const providerDescriptor1 = { ctor: TestProvider1, prefix: 'test', helpEntries: [] };
const providerDescriptor2 = { ctor: TestProvider2, prefix: 'test something', helpEntries: [] };
const providerDescriptor3 = { ctor: TestProvider3, prefix: 'changed', helpEntries: [] };
setup(() => {
instantiationService = workbenchInstantiationService();
accessor = instantiationService.createInstance(TestServiceAccessor);
});
test('registry', () => {
const registry = (Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess));
const restore = (registry as QuickAccessRegistry).clear();
assert.ok(!registry.getQuickAccessProvider('test'));
const disposables = new DisposableStore();
disposables.add(registry.registerQuickAccessProvider(providerDescriptorDefault));
assert(registry.getQuickAccessProvider('') === providerDescriptorDefault);
assert(registry.getQuickAccessProvider('test') === providerDescriptorDefault);
const disposable = disposables.add(registry.registerQuickAccessProvider(providerDescriptor1));
assert(registry.getQuickAccessProvider('test') === providerDescriptor1);
const providers = registry.getQuickAccessProviders();
assert(providers.some(provider => provider.prefix === 'test'));
disposable.dispose();
assert(registry.getQuickAccessProvider('test') === providerDescriptorDefault);
disposables.dispose();
assert.ok(!registry.getQuickAccessProvider('test'));
restore();
});
test('provider', async () => {
const registry = (Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess));
const restore = (registry as QuickAccessRegistry).clear();
const disposables = new DisposableStore();
disposables.add(registry.registerQuickAccessProvider(providerDescriptorDefault));
disposables.add(registry.registerQuickAccessProvider(providerDescriptor1));
disposables.add(registry.registerQuickAccessProvider(providerDescriptor2));
disposables.add(registry.registerQuickAccessProvider(providerDescriptor3));
accessor.quickInputService.quickAccess.show('test');
assert.strictEqual(providerDefaultCalled, false);
assert.strictEqual(provider1Called, true);
assert.strictEqual(provider2Called, false);
assert.strictEqual(provider3Called, false);
assert.strictEqual(providerDefaultCanceled, false);
assert.strictEqual(provider1Canceled, false);
assert.strictEqual(provider2Canceled, false);
assert.strictEqual(provider3Canceled, false);
assert.strictEqual(providerDefaultDisposed, false);
assert.strictEqual(provider1Disposed, false);
assert.strictEqual(provider2Disposed, false);
assert.strictEqual(provider3Disposed, false);
provider1Called = false;
accessor.quickInputService.quickAccess.show('test something');
assert.strictEqual(providerDefaultCalled, false);
assert.strictEqual(provider1Called, false);
assert.strictEqual(provider2Called, true);
assert.strictEqual(provider3Called, false);
assert.strictEqual(providerDefaultCanceled, false);
assert.strictEqual(provider1Canceled, true);
assert.strictEqual(provider2Canceled, false);
assert.strictEqual(provider3Canceled, false);
assert.strictEqual(providerDefaultDisposed, false);
assert.strictEqual(provider1Disposed, true);
assert.strictEqual(provider2Disposed, false);
assert.strictEqual(provider3Disposed, false);
provider2Called = false;
provider1Canceled = false;
provider1Disposed = false;
accessor.quickInputService.quickAccess.show('usedefault');
assert.strictEqual(providerDefaultCalled, true);
assert.strictEqual(provider1Called, false);
assert.strictEqual(provider2Called, false);
assert.strictEqual(provider3Called, false);
assert.strictEqual(providerDefaultCanceled, false);
assert.strictEqual(provider1Canceled, false);
assert.strictEqual(provider2Canceled, true);
assert.strictEqual(provider3Canceled, false);
assert.strictEqual(providerDefaultDisposed, false);
assert.strictEqual(provider1Disposed, false);
assert.strictEqual(provider2Disposed, true);
assert.strictEqual(provider3Disposed, false);
await timeout(1);
assert.strictEqual(providerDefaultCanceled, true);
assert.strictEqual(providerDefaultDisposed, true);
assert.strictEqual(provider3Called, true);
await timeout(1);
assert.strictEqual(provider3Canceled, true);
assert.strictEqual(provider3Disposed, true);
disposables.dispose();
restore();
});
let fastProviderCalled = false;
let slowProviderCalled = false;
let fastAndSlowProviderCalled = false;
let slowProviderCanceled = false;
let fastAndSlowProviderCanceled = false;
class FastTestQuickPickProvider extends PickerQuickAccessProvider<IQuickPickItem> {
constructor() {
super('fast');
}
protected _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array<IQuickPickItem> {
fastProviderCalled = true;
return [{ label: 'Fast Pick' }];
}
}
class SlowTestQuickPickProvider extends PickerQuickAccessProvider<IQuickPickItem> {
constructor() {
super('slow');
}
protected async _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IQuickPickItem>> {
slowProviderCalled = true;
await timeout(1);
if (token.isCancellationRequested) {
slowProviderCanceled = true;
}
return [{ label: 'Slow Pick' }];
}
}
class FastAndSlowTestQuickPickProvider extends PickerQuickAccessProvider<IQuickPickItem> {
constructor() {
super('bothFastAndSlow');
}
protected _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): FastAndSlowPicks<IQuickPickItem> {
fastAndSlowProviderCalled = true;
return {
picks: [{ label: 'Fast Pick' }],
additionalPicks: (async () => {
await timeout(1);
if (token.isCancellationRequested) {
fastAndSlowProviderCanceled = true;
}
return [{ label: 'Slow Pick' }];
})()
};
}
}
const fastProviderDescriptor = { ctor: FastTestQuickPickProvider, prefix: 'fast', helpEntries: [] };
const slowProviderDescriptor = { ctor: SlowTestQuickPickProvider, prefix: 'slow', helpEntries: [] };
const fastAndSlowProviderDescriptor = { ctor: FastAndSlowTestQuickPickProvider, prefix: 'bothFastAndSlow', helpEntries: [] };
test('quick pick access - show()', async () => {
const registry = (Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess));
const restore = (registry as QuickAccessRegistry).clear();
const disposables = new DisposableStore();
disposables.add(registry.registerQuickAccessProvider(fastProviderDescriptor));
disposables.add(registry.registerQuickAccessProvider(slowProviderDescriptor));
disposables.add(registry.registerQuickAccessProvider(fastAndSlowProviderDescriptor));
accessor.quickInputService.quickAccess.show('fast');
assert.strictEqual(fastProviderCalled, true);
assert.strictEqual(slowProviderCalled, false);
assert.strictEqual(fastAndSlowProviderCalled, false);
fastProviderCalled = false;
accessor.quickInputService.quickAccess.show('slow');
await timeout(2);
assert.strictEqual(fastProviderCalled, false);
assert.strictEqual(slowProviderCalled, true);
assert.strictEqual(slowProviderCanceled, false);
assert.strictEqual(fastAndSlowProviderCalled, false);
slowProviderCalled = false;
accessor.quickInputService.quickAccess.show('bothFastAndSlow');
await timeout(2);
assert.strictEqual(fastProviderCalled, false);
assert.strictEqual(slowProviderCalled, false);
assert.strictEqual(fastAndSlowProviderCalled, true);
assert.strictEqual(fastAndSlowProviderCanceled, false);
fastAndSlowProviderCalled = false;
accessor.quickInputService.quickAccess.show('slow');
accessor.quickInputService.quickAccess.show('bothFastAndSlow');
accessor.quickInputService.quickAccess.show('fast');
assert.strictEqual(fastProviderCalled, true);
assert.strictEqual(slowProviderCalled, true);
assert.strictEqual(fastAndSlowProviderCalled, true);
await timeout(2);
assert.strictEqual(slowProviderCanceled, true);
assert.strictEqual(fastAndSlowProviderCanceled, true);
disposables.dispose();
restore();
});
test('quick pick access - pick()', async () => {
const registry = (Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess));
const restore = (registry as QuickAccessRegistry).clear();
const disposables = new DisposableStore();
disposables.add(registry.registerQuickAccessProvider(fastProviderDescriptor));
const result = accessor.quickInputService.quickAccess.pick('fast');
assert.strictEqual(fastProviderCalled, true);
assert.ok(result instanceof Promise);
disposables.dispose();
restore();
});
});

View File

@@ -3,26 +3,27 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { basename } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorInput, EditorOptions, EditorsOrder, IFileEditorInput, IEditorInputFactoryRegistry, IEditorInputSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, SideBySideEditorInput, IEditorMoveEvent, EditorExtensions as Extensions } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorsOrder, IFileEditorInput, IEditorInputFactoryRegistry, IEditorInputSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, IEditorMoveEvent, EditorExtensions as Extensions, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor';
import { EditorServiceImpl, IEditorGroupView, IEditorGroupsAccessor, IEditorGroupTitleHeight } from 'vs/workbench/browser/parts/editor/editor';
import { Event, Emitter } from 'vs/base/common/event';
import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
import { IResolvedWorkingCopyBackup, IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchLayoutService, Parts, Position as PartPosition } from 'vs/workbench/services/layout/browser/layoutService';
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IEditorOptions, IResourceEditorInput, IEditorModel, ITextEditorOptions, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor';
import { IEditorOptions, IResourceEditorInput, IEditorModel, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor';
import { IUntitledTextEditorService, UntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ILifecycleService, BeforeShutdownEvent, ShutdownReason, StartupKind, LifecyclePhase, WillShutdownEvent } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { FileOperationEvent, IFileService, IFileStat, IResolveFileResult, FileChangesEvent, IResolveFileOptions, ICreateFileOptions, IFileSystemProvider, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileType, FileDeleteOptions, FileOverwriteOptions, FileWriteOptions, FileOpenOptions, IFileStatWithMetadata, IResolveMetadataFileOptions, IWriteFileOptions, IReadFileOptions, IFileContent, IFileStreamContent, FileOperationError, IFileSystemProviderWithFileReadStreamCapability, FileReadStreamOptions, IReadFileStreamOptions } from 'vs/platform/files/common/files';
import { FileOperationEvent, IFileService, IFileStat, IResolveFileResult, FileChangesEvent, IResolveFileOptions, ICreateFileOptions, IFileSystemProvider, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileType, FileDeleteOptions, FileOverwriteOptions, FileWriteOptions, FileOpenOptions, IFileStatWithMetadata, IResolveMetadataFileOptions, IWriteFileOptions, IReadFileOptions, IFileContent, IFileStreamContent, FileOperationError, IFileSystemProviderWithFileReadStreamCapability, FileReadStreamOptions, IReadFileStreamOptions, IFileSystemProviderCapabilitiesChangeEvent } from 'vs/platform/files/common/files';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
@@ -42,7 +43,7 @@ import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService, MockKeybindingService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { ITextBufferFactory, DefaultEndOfLine, EndOfLinePreference, ITextSnapshot } from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';
import { IRange, Range } from 'vs/editor/common/core/range';
import { IDialogService, IPickAndOpenOptions, ISaveDialogOptions, IOpenDialogOptions, IFileDialogService, ConfirmResult } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
@@ -51,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, IOpenEditorOverrideHandler, ISaveEditorsOptions, IRevertAllEditorsOptions, IResourceEditorInputType, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE, IOpenEditorOverrideEntry } from 'vs/workbench/services/editor/common/editorService';
import { IEditorService, ISaveEditorsOptions, IRevertAllEditorsOptions, IResourceEditorInputType, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE } 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';
@@ -74,7 +75,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
import product from 'vs/platform/product/common/product';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IWorkingCopyService, WorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { IWorkingCopyIdentifier } from 'vs/workbench/services/workingCopy/common/workingCopy';
import { IWorkingCopyBackupMeta, IWorkingCopyIdentifier } from 'vs/workbench/services/workingCopy/common/workingCopy';
import { IFilesConfigurationService, FilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
import { BrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
@@ -83,7 +84,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textModel';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
import { Direction } from 'vs/base/browser/ui/grid/grid';
import { IProgressService, IProgressOptions, IProgressWindowOptions, IProgressNotificationOptions, IProgressCompositeOptions, IProgress, IProgressStep, Progress } from 'vs/platform/progress/common/progress';
import { IProgressService, IProgressOptions, IProgressWindowOptions, IProgressNotificationOptions, IProgressCompositeOptions, IProgress, IProgressStep, Progress, IProgressDialogOptions } from 'vs/platform/progress/common/progress';
import { IWorkingCopyFileService, WorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
@@ -96,7 +97,7 @@ import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogSer
import { CodeEditorService } from 'vs/workbench/services/editor/browser/codeEditorService';
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IDiffEditor, IEditor } from 'vs/editor/common/editorCommon';
import { IChange, IDiffEditor, IEditor } from 'vs/editor/common/editorCommon';
import { IInputBox, IInputOptions, IPickOptions, IQuickInputButton, IQuickInputService, IQuickNavigateConfiguration, IQuickPick, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { QuickInputService } from 'vs/workbench/services/quickinput/browser/quickInputService';
import { IListService } from 'vs/platform/list/browser/listService';
@@ -119,34 +120,38 @@ import { FileService } from 'vs/platform/files/common/fileService';
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
import { TestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor';
import { IEnterWorkspaceResult, IRecent, IRecentlyOpened, IWorkspaceFolderCreationData, IWorkspaceIdentifier, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
import { TestWorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { ILocalTerminalService, IShellLaunchConfig, ITerminalChildProcess, ITerminalsLayoutInfo, ITerminalsLayoutInfoById } from 'vs/platform/terminal/common/terminal';
import { IWorkspaceTrustManagementService, IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
import { TestWorkspaceTrustManagementService, TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { ILocalTerminalService, IShellLaunchConfig, ITerminalChildProcess, ITerminalProfile, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal';
import { IProcessDetails, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess';
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { isArray } from 'vs/base/common/types';
import { IShellLaunchConfigResolveOptions, ITerminalProfile, ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal';
import { IShellLaunchConfigResolveOptions, ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal';
import { EditorOverrideService } from 'vs/workbench/services/editor/browser/editorOverrideService';
import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files';
import { IEditorOverrideService } from 'vs/workbench/services/editor/common/editorOverrideService';
import { IWorkingCopyEditorService, WorkingCopyEditorService } from 'vs/workbench/services/workingCopy/common/workingCopyEditorService';
import { IElevatedFileService } from 'vs/workbench/services/files/common/elevatedFileService';
import { BrowserElevatedFileService } from 'vs/workbench/services/files/browser/elevatedFileService';
import { IDiffComputationResult, IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { TextEdit, IInplaceReplaceSupportResult } from 'vs/editor/common/modes';
import { ResourceMap } from 'vs/base/common/map';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
export function createFileEditorInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput {
return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined, undefined, undefined, undefined);
return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined, undefined, undefined, undefined, undefined);
}
Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).registerFileEditorInputFactory({
typeId: FILE_EDITOR_INPUT_ID,
createFileEditorInput: (resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredMode, instantiationService): IFileEditorInput => {
return instantiationService.createInstance(FileEditorInput, resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredMode);
createFileEditorInput: (resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredMode, preferredContents, instantiationService): IFileEditorInput => {
return instantiationService.createInstance(FileEditorInput, resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredMode, preferredContents);
},
isFileEditorInput: (obj): obj is IFileEditorInput => {
@@ -183,6 +188,7 @@ export function workbenchInstantiationService(
): ITestInstantiationService {
const instantiationService = new TestInstantiationService(new ServiceCollection([ILifecycleService, new TestLifecycleService()]));
instantiationService.stub(IEditorWorkerService, new TestEditorWorkerService());
instantiationService.stub(IWorkingCopyService, disposables.add(new WorkingCopyService()));
instantiationService.stub(IEnvironmentService, TestEnvironmentService);
instantiationService.stub(IWorkbenchEnvironmentService, TestEnvironmentService);
@@ -223,7 +229,6 @@ export function workbenchInstantiationService(
instantiationService.stub(IKeybindingService, keybindingService);
instantiationService.stub(IDecorationsService, new TestDecorationsService());
instantiationService.stub(IExtensionService, new TestExtensionService());
instantiationService.stub(IWorkingCopyEditorService, disposables.add(instantiationService.createInstance(WorkingCopyEditorService)));
instantiationService.stub(IWorkingCopyFileService, disposables.add(instantiationService.createInstance(WorkingCopyFileService)));
instantiationService.stub(ITextFileService, overrides?.textFileService ? overrides.textFileService(instantiationService) : disposables.add(<ITextFileService>instantiationService.createInstance(TestTextFileService)));
instantiationService.stub(IHostService, <IHostService>instantiationService.createInstance(TestHostService));
@@ -234,6 +239,7 @@ export function workbenchInstantiationService(
instantiationService.stub(ILabelService, <ILabelService>disposables.add(instantiationService.createInstance(LabelService)));
const editorService = overrides?.editorService ? overrides.editorService(instantiationService) : new TestEditorService(editorGroupService);
instantiationService.stub(IEditorService, editorService);
instantiationService.stub(IWorkingCopyEditorService, disposables.add(instantiationService.createInstance(WorkingCopyEditorService)));
instantiationService.stub(IEditorOverrideService, disposables.add(instantiationService.createInstance(EditorOverrideService)));
instantiationService.stub(ICodeEditorService, disposables.add(new CodeEditorService(editorService, themeService, configService)));
instantiationService.stub(IViewletService, new TestViewletService());
@@ -258,9 +264,13 @@ export class TestServiceAccessor {
@IModelService public modelService: ModelServiceImpl,
@IFileService public fileService: TestFileService,
@IFileDialogService public fileDialogService: TestFileDialogService,
@IDialogService public dialogService: TestDialogService,
@IWorkingCopyService public workingCopyService: IWorkingCopyService,
@IEditorService public editorService: TestEditorService,
@IWorkbenchEnvironmentService public environmentService: IWorkbenchEnvironmentService,
@IPathService public pathService: IPathService,
@IEditorGroupsService public editorGroupService: IEditorGroupsService,
@IEditorOverrideService public editorOverrideService: IEditorOverrideService,
@IModeService public modeService: IModeService,
@ITextModelService public textModelResolverService: ITextModelService,
@IUntitledTextEditorService public untitledTextEditorService: UntitledTextEditorService,
@@ -275,7 +285,8 @@ export class TestServiceAccessor {
@INotificationService public notificationService: INotificationService,
@IWorkingCopyEditorService public workingCopyEditorService: IWorkingCopyEditorService,
@IInstantiationService public instantiationService: IInstantiationService,
@IElevatedFileService public elevatedFileService: IElevatedFileService
@IElevatedFileService public elevatedFileService: IElevatedFileService,
@IWorkspaceTrustRequestService public workspaceTrustRequestService: TestWorkspaceTrustRequestService
) { }
}
@@ -321,8 +332,8 @@ export class TestTextFileService extends BrowserTextFileService {
workingCopyFileService,
uriIdentityService,
modeService,
logService,
elevatedFileService
elevatedFileService,
logService
);
}
@@ -347,7 +358,8 @@ export class TestTextFileService extends BrowserTextFileService {
etag: content.etag,
encoding: 'utf8',
value: await createTextBufferFactoryFromStream(content.value),
size: 10
size: 10,
readonly: false
};
}
@@ -405,7 +417,7 @@ export class TestProgressService implements IProgressService {
declare readonly _serviceBrand: undefined;
withProgress(
options: IProgressOptions | IProgressWindowOptions | IProgressNotificationOptions | IProgressCompositeOptions,
options: IProgressOptions | IProgressDialogOptions | IProgressWindowOptions | IProgressNotificationOptions | IProgressCompositeOptions,
task: (progress: IProgress<IProgressStep>) => Promise<any>,
onDidCancel?: ((choice?: number | undefined) => void) | undefined
): Promise<any> {
@@ -532,6 +544,7 @@ export class TestLayoutService implements IWorkbenchLayoutService {
isStatusBarHidden(): boolean { return false; }
isActivityBarHidden(): boolean { return false; }
setActivityBarHidden(_hidden: boolean): void { }
setBannerHidden(_hidden: boolean): void { }
isSideBarHidden(): boolean { return false; }
async setEditorHidden(_hidden: boolean): Promise<void> { }
async setSideBarHidden(_hidden: boolean): Promise<void> { }
@@ -650,7 +663,6 @@ export class TestEditorGroupsService implements IEditorGroupsService {
get activeGroup(): IEditorGroup { return this.groups[0]; }
get count(): number { return this.groups.length; }
isRestored(): boolean { return true; }
getGroups(_order?: GroupsOrder): readonly IEditorGroup[] { return this.groups; }
getGroup(identifier: number): IEditorGroup | undefined { return this.groups.find(group => group.id === identifier); }
getLabel(_identifier: number): string { return 'Group 1'; }
@@ -709,6 +721,7 @@ export class TestEditorGroupView implements IEditorGroupView {
onDidFocus: Event<void> = Event.None;
onDidChange: Event<{ width: number; height: number; }> = Event.None;
onWillMoveEditor: Event<IEditorMoveEvent> = Event.None;
onWillOpenEditor: Event<IEditorOpenEvent> = Event.None;
getEditors(_order?: EditorsOrder): readonly IEditorInput[] { return []; }
findEditors(_resource: URI): readonly IEditorInput[] { return []; }
@@ -720,8 +733,8 @@ export class TestEditorGroupView implements IEditorGroupView {
isSticky(_editor: IEditorInput): boolean { return false; }
isActive(_editor: IEditorInput): boolean { return false; }
contains(candidate: IEditorInput): boolean { return false; }
moveEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions | ITextEditorOptions): void { }
copyEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions | ITextEditorOptions): void { }
moveEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions): void { }
copyEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions): void { }
async closeEditor(_editor?: IEditorInput, options?: ICloseEditorOptions): Promise<void> { }
async closeEditors(_editors: IEditorInput[] | ICloseEditorsFilter, options?: ICloseEditorOptions): Promise<void> { }
async closeAllEditors(options?: ICloseAllEditorsOptions): Promise<void> { }
@@ -792,15 +805,13 @@ export class TestEditorService implements EditorServiceImpl {
constructor(private editorGroupService?: IEditorGroupsService) { }
getEditors() { return []; }
findEditors() { return [] as any; }
getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][] { return []; }
overrideOpenEditor(_handler: IOpenEditorOverrideHandler): IDisposable { return toDisposable(() => undefined); }
openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditorPane | undefined>;
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 | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | ITextEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditorPane | undefined> {
async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditorPane | undefined> {
throw new Error('not implemented');
}
doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType): [IEditorGroup, EditorInput, EditorOptions | undefined] | undefined {
doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined {
if (!this.editorGroupService) {
return undefined;
}
@@ -822,24 +833,31 @@ export class TestFileService implements IFileService {
declare readonly _serviceBrand: undefined;
private readonly _onDidFilesChange = new Emitter<FileChangesEvent>();
get onDidFilesChange(): Event<FileChangesEvent> { return this._onDidFilesChange.event; }
fireFileChanges(event: FileChangesEvent): void { this._onDidFilesChange.fire(event); }
private readonly _onDidRunOperation = new Emitter<FileOperationEvent>();
get onDidRunOperation(): Event<FileOperationEvent> { return this._onDidRunOperation.event; }
fireAfterOperation(event: FileOperationEvent): void { this._onDidRunOperation.fire(event); }
private readonly _onDidChangeFileSystemProviderCapabilities = new Emitter<IFileSystemProviderCapabilitiesChangeEvent>();
get onDidChangeFileSystemProviderCapabilities(): Event<IFileSystemProviderCapabilitiesChangeEvent> { return this._onDidChangeFileSystemProviderCapabilities.event; }
fireFileSystemProviderCapabilitiesChangeEvent(event: IFileSystemProviderCapabilitiesChangeEvent): void { this._onDidChangeFileSystemProviderCapabilities.fire(event); }
readonly onWillActivateFileSystemProvider = Event.None;
readonly onDidChangeFileSystemProviderCapabilities = Event.None;
readonly onError: Event<Error> = Event.None;
private content = 'Hello Html';
private lastReadFileUri!: URI;
readonly = false;
setContent(content: string): void { this.content = content; }
getContent(): string { return this.content; }
getLastReadFileUri(): URI { return this.lastReadFileUri; }
get onDidFilesChange(): Event<FileChangesEvent> { return this._onDidFilesChange.event; }
fireFileChanges(event: FileChangesEvent): void { this._onDidFilesChange.fire(event); }
get onDidRunOperation(): Event<FileOperationEvent> { return this._onDidRunOperation.event; }
fireAfterOperation(event: FileOperationEvent): void { this._onDidRunOperation.fire(event); }
resolve(resource: URI, _options?: IResolveFileOptions): Promise<IFileStat>;
resolve(resource: URI, _options: IResolveMetadataFileOptions): Promise<IFileStatWithMetadata>;
resolve(resource: URI, _options?: IResolveFileOptions): Promise<IFileStat>;
resolve(resource: URI, _options?: IResolveFileOptions): Promise<IFileStat> {
return Promise.resolve({
resource,
@@ -850,6 +868,7 @@ export class TestFileService implements IFileService {
isFile: true,
isDirectory: false,
isSymbolicLink: false,
readonly: this.readonly,
name: basename(resource)
});
}
@@ -860,7 +879,7 @@ export class TestFileService implements IFileService {
return stats.map(stat => ({ stat, success: true }));
}
readonly notExistsSet = new Set<URI>();
readonly notExistsSet = new ResourceMap<boolean>();
async exists(_resource: URI): Promise<boolean> { return !this.notExistsSet.has(_resource); }
@@ -881,6 +900,7 @@ export class TestFileService implements IFileService {
mtime: Date.now(),
ctime: Date.now(),
name: basename(resource),
readonly: this.readonly,
size: 1
});
}
@@ -900,6 +920,7 @@ export class TestFileService implements IFileService {
mtime: Date.now(),
ctime: Date.now(),
size: 1,
readonly: this.readonly,
name: basename(resource)
});
}
@@ -922,6 +943,7 @@ export class TestFileService implements IFileService {
isFile: true,
isDirectory: false,
isSymbolicLink: false,
readonly: this.readonly,
name: basename(resource)
});
}
@@ -958,7 +980,9 @@ export class TestFileService implements IFileService {
return true;
}
return false;
const provider = this.getProvider(resource.scheme);
return !!(provider && (provider.capabilities & capability));
}
async del(_resource: URI, _options?: { useTrash?: boolean, recursive?: boolean; }): Promise<void> { }
@@ -981,6 +1005,8 @@ export class TestFileService implements IFileService {
export class TestWorkingCopyBackupService extends InMemoryWorkingCopyBackupService {
readonly resolved: Set<IWorkingCopyIdentifier> = new Set();
constructor() {
super();
}
@@ -992,6 +1018,12 @@ export class TestWorkingCopyBackupService extends InMemoryWorkingCopyBackupServi
return textBuffer.getValueInRange(range, EndOfLinePreference.TextDefined);
}
override async resolve<T extends IWorkingCopyBackupMeta>(identifier: IWorkingCopyIdentifier): Promise<IResolvedWorkingCopyBackup<T> | undefined> {
this.resolved.add(identifier);
return super.resolve(identifier);
}
}
export function toUntypedWorkingCopyId(resource: URI): IWorkingCopyIdentifier {
@@ -1183,7 +1215,6 @@ export class TestInMemoryFileSystemProvider extends InMemoryFileSystemProvider i
| FileSystemProviderCapabilities.PathCaseSensitive
| FileSystemProviderCapabilities.FileReadStream;
readFileStream(resource: URI): ReadableStreamEvents<Uint8Array> {
const BUFFER_SIZE = 64 * 1024;
const stream = newWriteableStream<Uint8Array>(data => VSBuffer.concat(data.map(data => VSBuffer.wrap(data))).buffer);
@@ -1281,7 +1312,7 @@ export function registerTestEditor(id: string, inputs: SyncDescriptor<EditorInpu
this._scopedContextKeyService = new MockContextKeyService();
}
override async setInput(input: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
override async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
super.setInput(input, options, context, token);
await input.resolve();
@@ -1343,7 +1374,7 @@ export function registerTestFileEditor(): IDisposable {
TestTextFileEditor.ID,
'Text File Editor'
),
[new SyncDescriptor<EditorInput>(FileEditorInput)]
[new SyncDescriptor(FileEditorInput)]
));
return disposables;
@@ -1359,8 +1390,8 @@ export function registerTestResourceEditor(): IDisposable {
'Text Editor'
),
[
new SyncDescriptor<EditorInput>(UntitledTextEditorInput),
new SyncDescriptor<EditorInput>(ResourceEditorInput)
new SyncDescriptor(UntitledTextEditorInput),
new SyncDescriptor(TextResourceEditorInput)
]
));
@@ -1403,6 +1434,16 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput
}
override get typeId() { return this._typeId; }
private _capabilities: EditorInputCapabilities = EditorInputCapabilities.None;
override get capabilities(): EditorInputCapabilities { return this._capabilities; }
override set capabilities(capabilities: EditorInputCapabilities) {
if (this._capabilities !== capabilities) {
this._capabilities = capabilities;
this._onDidChangeCapabilities.fire();
}
}
override resolve(): Promise<IEditorModel | null> { return !this.fails ? Promise.resolve(null) : Promise.reject(new Error('fails')); }
override matches(other: EditorInput): boolean { return !!(other?.resource && this.resource.toString() === other.resource.toString() && other instanceof TestFileEditorInput && other.typeId === this.typeId); }
setPreferredResource(resource: URI): void { }
@@ -1411,6 +1452,7 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput
setPreferredName(name: string): void { }
setPreferredDescription(description: string): void { }
setPreferredEncoding(encoding: string) { }
setPreferredContents(contents: string): void { }
setMode(mode: string) { }
setPreferredMode(mode: string) { }
setForceOpenAsBinary(): void { }
@@ -1436,9 +1478,6 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput
override isDirty(): boolean {
return this.dirty;
}
override isReadonly(): boolean {
return false;
}
isResolved(): boolean { return false; }
override dispose(): void {
super.dispose();
@@ -1538,40 +1577,32 @@ export class TestWorkspacesService implements IWorkspacesService {
async clearRecentlyOpened(): Promise<void> { }
async getRecentlyOpened(): Promise<IRecentlyOpened> { return { files: [], workspaces: [] }; }
async getDirtyWorkspaces(): Promise<(URI | IWorkspaceIdentifier)[]> { return []; }
async enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | null> { throw new Error('Method not implemented.'); }
async enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | undefined> { throw new Error('Method not implemented.'); }
async getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier> { throw new Error('Method not implemented.'); }
}
export class TestTerminalInstanceService implements ITerminalInstanceService {
declare readonly _serviceBrand: undefined;
async getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }> {
return {
shell: 'bash',
args: undefined
};
}
async getMainProcessParentEnv(): Promise<IProcessEnvironment> {
return {};
}
async getXtermConstructor(): Promise<any> { throw new Error('Method not implemented.'); }
async getXtermSearchConstructor(): Promise<any> { throw new Error('Method not implemented.'); }
async getXtermUnicode11Constructor(): Promise<any> { throw new Error('Method not implemented.'); }
async getXtermWebglConstructor(): Promise<any> { throw new Error('Method not implemented.'); }
createWindowsShellHelper(shellProcessId: number, xterm: any): any { throw new Error('Method not implemented.'); }
preparePathForTerminalAsync(path: string, executable: string | undefined, title: string, shellType: TerminalShellType, isRemote: boolean): Promise<string> { throw new Error('Method not implemented.'); }
}
export class TestTerminalProfileResolverService implements ITerminalProfileResolverService {
_serviceBrand: undefined;
defaultProfileName = '';
resolveIcon(shellLaunchConfig: IShellLaunchConfig): void { }
async resolveShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig, options: IShellLaunchConfigResolveOptions): Promise<void> { }
async getDefaultProfile(options: IShellLaunchConfigResolveOptions): Promise<ITerminalProfile> { return { path: '/default', profileName: 'Default' }; }
async getDefaultProfile(options: IShellLaunchConfigResolveOptions): Promise<ITerminalProfile> { return { path: '/default', profileName: 'Default', isDefault: true }; }
async getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise<string> { return '/default'; }
async getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise<string | string[]> { return []; }
async getShellEnvironment(): Promise<IProcessEnvironment> { return process.env; }
async getEnvironment(): Promise<IProcessEnvironment> { return process.env; }
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined { return undefined; }
getSafeConfigValueFullKey(key: string): unknown | undefined { return undefined; }
createProfileFromShellAndShellArgs(shell?: unknown, shellArgs?: unknown): Promise<string | ITerminalProfile> { throw new Error('Method not implemented.'); }
}
export class TestLocalTerminalService implements ILocalTerminalService {
@@ -1588,11 +1619,16 @@ export class TestLocalTerminalService implements ILocalTerminalService {
async attachToProcess(id: number): Promise<ITerminalChildProcess | undefined> { throw new Error('Method not implemented.'); }
async listProcesses(): Promise<IProcessDetails[]> { throw new Error('Method not implemented.'); }
getDefaultSystemShell(osOverride?: OperatingSystem): Promise<string> { throw new Error('Method not implemented.'); }
getShellEnvironment(): Promise<IProcessEnvironment> { throw new Error('Method not implemented.'); }
getProfiles(isWorkspaceTrusted: boolean, includeDetectedProfiles?: boolean): Promise<ITerminalProfile[]> { throw new Error('Method not implemented.'); }
getEnvironment(): Promise<IProcessEnvironment> { throw new Error('Method not implemented.'); }
getShellEnvironment(): Promise<IProcessEnvironment | undefined> { throw new Error('Method not implemented.'); }
getWslPath(original: string): Promise<string> { throw new Error('Method not implemented.'); }
async setTerminalLayoutInfo(argsOrLayout?: ISetTerminalLayoutInfoArgs | ITerminalsLayoutInfoById) { throw new Error('Method not implemented.'); }
async getTerminalLayoutInfo(): Promise<ITerminalsLayoutInfo | undefined> { throw new Error('Method not implemented.'); }
async reduceConnectionGraceTime(): Promise<void> { throw new Error('Method not implemented.'); }
processBinary(id: number, data: string): Promise<void> { throw new Error('Method not implemented.'); }
updateTitle(id: number, title: string): Promise<void> { throw new Error('Method not implemented.'); }
updateIcon(id: number, icon: URI | { light: URI; dark: URI } | { id: string, color?: { id: string } }, color?: string): Promise<void> { throw new Error('Method not implemented.'); }
}
class TestTerminalChildProcess implements ITerminalChildProcess {
@@ -1650,3 +1686,18 @@ export class TestQuickInputService implements IQuickInputService {
back(): Promise<void> { throw new Error('not implemented.'); }
cancel(): Promise<void> { throw new Error('not implemented.'); }
}
export class TestEditorWorkerService implements IEditorWorkerService {
declare readonly _serviceBrand: undefined;
canComputeDiff(original: URI, modified: URI): boolean { return false; }
async computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean, maxComputationTime: number): Promise<IDiffComputationResult | null> { return null; }
canComputeDirtyDiff(original: URI, modified: URI): boolean { return false; }
async computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise<IChange[] | null> { return null; }
async computeMoreMinimalEdits(resource: URI, edits: TextEdit[] | null | undefined): Promise<TextEdit[] | undefined> { return undefined; }
canComputeWordRanges(resource: URI): boolean { return false; }
async computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[]; } | null> { return null; }
canNavigateValueSet(resource: URI): boolean { return false; }
async navigateValueSet(resource: URI, range: IRange, up: boolean): Promise<IInplaceReplaceSupportResult | null> { return null; }
}

View File

@@ -10,6 +10,7 @@ import { INotification, Severity, NotificationsFilter } from 'vs/platform/notifi
import { createErrorWithActions } from 'vs/base/common/errors';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { timeout } from 'vs/base/common/async';
suite('Notifications', () => {
@@ -143,6 +144,23 @@ suite('Notifications', () => {
assert.strictEqual(item11.silent, true);
});
test('Items - does not fire changed when message did not change (content, severity)', async () => {
const item1 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' })!;
let fired = false;
item1.onDidChangeContent(() => {
fired = true;
});
item1.updateMessage('Error Message');
await timeout(0);
assert.ok(!fired, 'Expected onDidChangeContent to not be fired');
item1.updateSeverity(Severity.Error);
await timeout(0);
assert.ok(!fired, 'Expected onDidChangeContent to not be fired');
});
test('Model', () => {
const model = new NotificationsModel();
@@ -167,11 +185,11 @@ suite('Notifications', () => {
assert.strictEqual(lastNotificationEvent.index, 0);
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);
item1Handle.updateMessage('Error Message');
item1Handle.updateMessage('Different Error Message');
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);
assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.MESSAGE);
item1Handle.updateSeverity(Severity.Error);
item1Handle.updateSeverity(Severity.Warning);
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);
assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.SEVERITY);
@@ -205,8 +223,8 @@ suite('Notifications', () => {
item1Handle.close();
assert.strictEqual(called, 1);
assert.strictEqual(model.notifications.length, 2);
assert.strictEqual(lastNotificationEvent.item.severity, item1.severity);
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item1.message);
assert.strictEqual(lastNotificationEvent.item.severity, Severity.Warning);
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), 'Different Error Message');
assert.strictEqual(lastNotificationEvent.index, 2);
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.REMOVE);

View File

@@ -145,7 +145,7 @@ export class TestWorkingCopy extends Disposable implements IWorkingCopy {
private dirty = false;
constructor(public readonly resource: URI, isDirty = false, public readonly typeId = 'testWorkingCopyType') {
constructor(readonly resource: URI, isDirty = false, readonly typeId = 'testWorkingCopyType') {
super();
this.dirty = isDirty;

View File

@@ -883,14 +883,16 @@ suite('ExtHostSearch', () => {
});
test('basic sibling clause', async () => {
mockPFS.readdir = (_path: string): any => {
if (_path === rootFolderA.fsPath) {
return Promise.resolve([
'file1.js',
'file1.ts'
]);
} else {
return Promise.reject(new Error('Wrong path'));
(mockPFS as any).Promises = {
readdir: (_path: string): any => {
if (_path === rootFolderA.fsPath) {
return Promise.resolve([
'file1.js',
'file1.ts'
]);
} else {
return Promise.reject(new Error('Wrong path'));
}
}
};
@@ -926,21 +928,23 @@ suite('ExtHostSearch', () => {
});
test('multiroot sibling clause', async () => {
mockPFS.readdir = (_path: string): any => {
if (_path === joinPath(rootFolderA, 'folder').fsPath) {
return Promise.resolve([
'fileA.scss',
'fileA.css',
'file2.css'
]);
} else if (_path === rootFolderB.fsPath) {
return Promise.resolve([
'fileB.ts',
'fileB.js',
'file3.js'
]);
} else {
return Promise.reject(new Error('Wrong path'));
(mockPFS as any).Promises = {
readdir: (_path: string): any => {
if (_path === joinPath(rootFolderA, 'folder').fsPath) {
return Promise.resolve([
'fileA.scss',
'fileA.css',
'file2.css'
]);
} else if (_path === rootFolderB.fsPath) {
return Promise.resolve([
'fileB.ts',
'fileB.js',
'file3.js'
]);
} else {
return Promise.reject(new Error('Wrong path'));
}
}
};

View File

@@ -31,7 +31,7 @@ suite('MainThreadWorkspace', () => {
assert.strictEqual(query.folderQueries.length, 1);
assert.strictEqual(query.folderQueries[0].disregardIgnoreFiles, true);
assert.deepEqual(query.includePattern, { 'foo': true });
assert.deepStrictEqual({ ...query.includePattern }, { 'foo': true });
assert.strictEqual(query.maxResults, 10);
return Promise.resolve({ results: [], messages: [] });
@@ -89,7 +89,7 @@ suite('MainThreadWorkspace', () => {
instantiationService.stub(ISearchService, {
fileSearch(query: IFileQuery) {
assert.strictEqual(query.folderQueries[0].excludePattern, undefined);
assert.deepEqual(query.excludePattern, { 'exclude/**': true });
assert.deepStrictEqual({ ...query.excludePattern }, { 'exclude/**': true });
return Promise.resolve({ results: [], messages: [] });
}

View File

@@ -6,7 +6,6 @@
import { Registry } from 'vs/platform/registry/common/platform';
import { IColorRegistry, Extensions, ColorContribution } from 'vs/platform/theme/common/colorRegistry';
import { asText } from 'vs/platform/request/common/request';
import * as fs from 'fs';
import * as pfs from 'vs/base/node/pfs';
import * as path from 'vs/base/common/path';
import * as assert from 'assert';
@@ -102,11 +101,11 @@ function getDescription(color: ColorContribution) {
async function getColorsFromExtension(): Promise<{ [id: string]: string }> {
let extPath = getPathFromAmdModule(require, '../../../../../extensions');
let extFolders = await pfs.readDirsInDir(extPath);
let extFolders = await pfs.Promises.readDirsInDir(extPath);
let result: { [id: string]: string } = Object.create(null);
for (let folder of extFolders) {
try {
let packageJSON = JSON.parse((await fs.promises.readFile(path.join(extPath, folder, 'package.json'))).toString());
let packageJSON = JSON.parse((await pfs.Promises.readFile(path.join(extPath, folder, 'package.json'))).toString());
let contributes = packageJSON['contributes'];
if (contributes) {
let colors = contributes['colors'];

View File

@@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Color } from 'vs/base/common/color';
import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions, IColorRegistry } from 'vs/platform/theme/common/colorRegistry';
suite('ColorRegistry', () => {
if (process.env.VSCODE_COLOR_REGISTRY_EXPORT) {
test('exports', () => {
const themingRegistry = Registry.as<IColorRegistry>(Extensions.ColorContribution);
const colors = themingRegistry.getColors();
const replacer = (_key: string, value: unknown) =>
value instanceof Color ? Color.Format.CSS.formatHexA(value) : value;
console.log(`#colors:${JSON.stringify(colors, replacer)}\n`);
});
}
});

View File

@@ -23,7 +23,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { URI } from 'vs/base/common/uri';
import { IReadTextFileOptions, ITextFileStreamContent, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textModel';
import { IOpenEmptyWindowOptions, IWindowOpenable, IOpenWindowOptions, IOpenedWindow } from 'vs/platform/windows/common/windows';
import { IOpenEmptyWindowOptions, IWindowOpenable, IOpenWindowOptions, IOpenedWindow, IPartsSplash } from 'vs/platform/windows/common/windows';
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
import { LogLevel, ILogService } from 'vs/platform/log/common/log';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
@@ -53,7 +53,6 @@ export const TestWorkbenchConfiguration: INativeWorkbenchConfiguration = {
machineId: 'testMachineId',
logLevel: LogLevel.Error,
mainPid: 0,
partsSplashPath: '',
appRoot: '',
userEnv: {},
execPath: process.execPath,
@@ -136,7 +135,8 @@ export class TestTextFileService extends NativeTextFileService {
etag: content.etag,
encoding: 'utf8',
value: await createTextBufferFactoryFromStream(content.value),
size: 10
size: 10,
readonly: false
};
}
}
@@ -197,6 +197,7 @@ export class TestNativeHostService implements INativeHostService {
async unmaximizeWindow(): Promise<void> { }
async minimizeWindow(): Promise<void> { }
async setMinimumSize(width: number | undefined, height: number | undefined): Promise<void> { }
async saveWindowSplash(value: IPartsSplash): Promise<void> { }
async focusWindow(options?: { windowId?: number | undefined; } | undefined): Promise<void> { }
async showMessageBox(options: Electron.MessageBoxOptions): Promise<Electron.MessageBoxReturnValue> { throw new Error('Method not implemented.'); }
async showSaveDialog(options: Electron.SaveDialogOptions): Promise<Electron.SaveDialogReturnValue> { throw new Error('Method not implemented.'); }
@@ -216,13 +217,15 @@ export class TestNativeHostService implements INativeHostService {
async setDocumentEdited(edited: boolean): Promise<void> { }
async openExternal(url: string): Promise<boolean> { return false; }
async updateTouchBar(): Promise<void> { }
async moveItemToTrash(): Promise<boolean> { return false; }
async moveItemToTrash(): Promise<void> { }
async newWindowTab(): Promise<void> { }
async showPreviousWindowTab(): Promise<void> { }
async showNextWindowTab(): Promise<void> { }
async moveWindowTabToNewWindow(): Promise<void> { }
async mergeAllWindowTabs(): Promise<void> { }
async toggleWindowTabsBar(): Promise<void> { }
async installShellCommand(): Promise<void> { }
async uninstallShellCommand(): Promise<void> { }
async notifyReady(): Promise<void> { }
async relaunch(options?: { addArgs?: string[] | undefined; removeArgs?: string[] | undefined; } | undefined): Promise<void> { }
async reload(): Promise<void> { }