VS Code merge to df8fe74bd55313de0dd2303bc47a4aab0ca56b0e (#17979)

* Merge from vscode 504f934659740e9d41501cad9f162b54d7745ad9

* delete unused folders

* distro

* Bump build node version

* update chokidar

* FIx hygiene errors

* distro

* Fix extension lint issues

* Remove strict-vscode

* Add copyright header exemptions

* Bump vscode-extension-telemetry to fix webpacking issue with zone.js

* distro

* Fix failing tests (revert marked.js back to current one until we decide to update)

* Skip searchmodel test

* Fix mac build

* temp debug script loading

* Try disabling coverage

* log error too

* Revert "log error too"

This reverts commit af0183e5d4ab458fdf44b88fbfab9908d090526f.

* Revert "temp debug script loading"

This reverts commit 3d687d541c76db2c5b55626c78ae448d3c25089c.

* Add comments explaining coverage disabling

* Fix ansi_up loading issue

* Merge latest from ads

* Use newer option

* Fix compile

* add debug logging warn

* Always log stack

* log more

* undo debug

* Update to use correct base path (+cleanup)

* distro

* fix compile errors

* Remove strict-vscode

* Fix sql editors not showing

* Show db dropdown input & fix styling

* Fix more info in gallery

* Fix gallery asset requests

* Delete unused workflow

* Fix tapable resolutions for smoke test compile error

* Fix smoke compile

* Disable crash reporting

* Disable interactive

Co-authored-by: ADS Merger <karlb@microsoft.com>
This commit is contained in:
Charles Gagnon
2022-01-06 09:06:56 -08:00
committed by GitHub
parent fd2736b6a6
commit 2bc6a0cd01
2099 changed files with 79520 additions and 43813 deletions

View File

@@ -1292,7 +1292,7 @@ suite('ExtHostLanguageFeatureCommands', function () {
assert.ok(value[0].parent);
});
// --- call hierarcht
// --- call hierarchy
test('CallHierarchy, back and forth', async function () {
@@ -1335,6 +1335,40 @@ suite('ExtHostLanguageFeatureCommands', function () {
assert.strictEqual(outgoing[0].to.name, 'OUTGOING');
});
// --- type hierarchy
test('TypeHierarchy, back and forth', async function () {
disposables.push(extHost.registerTypeHierarchyProvider(nullExtensionDescription, defaultSelector, new class implements vscode.TypeHierarchyProvider {
prepareTypeHierarchy(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<vscode.TypeHierarchyItem[]> {
return [new types.TypeHierarchyItem(types.SymbolKind.Constant, 'ROOT', 'ROOT', document.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0))];
}
provideTypeHierarchySupertypes(item: vscode.TypeHierarchyItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.TypeHierarchyItem[]> {
return [new types.TypeHierarchyItem(types.SymbolKind.Constant, 'SUPER', 'SUPER', item.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0))];
}
provideTypeHierarchySubtypes(item: vscode.TypeHierarchyItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.TypeHierarchyItem[]> {
return [new types.TypeHierarchyItem(types.SymbolKind.Constant, 'SUB', 'SUB', item.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0))];
}
}));
await rpcProtocol.sync();
const root = await commands.executeCommand<vscode.TypeHierarchyItem[]>('vscode.prepareTypeHierarchy', model.uri, new types.Position(0, 0));
assert.ok(Array.isArray(root));
assert.strictEqual(root.length, 1);
assert.strictEqual(root[0].name, 'ROOT');
const incoming = await commands.executeCommand<vscode.TypeHierarchyItem[]>('vscode.provideSupertypes', root[0]);
assert.strictEqual(incoming.length, 1);
assert.strictEqual(incoming[0].name, 'SUPER');
const outgoing = await commands.executeCommand<vscode.TypeHierarchyItem[]>('vscode.provideSubtypes', root[0]);
assert.strictEqual(outgoing.length, 1);
assert.strictEqual(outgoing[0].name, 'SUB');
});
test('selectionRangeProvider on inner array always returns outer array #91852', async function () {
disposables.push(extHost.registerSelectionRangeProvider(nullExtensionDescription, defaultSelector, <vscode.SelectionRangeProvider>{

View File

@@ -104,6 +104,8 @@ suite('ExtHostDocumentData', () => {
}],
eol: undefined!,
versionId: undefined!,
isRedoing: false,
isUndoing: false,
});
// line didn't change
@@ -161,6 +163,8 @@ suite('ExtHostDocumentData', () => {
}],
eol: undefined!,
versionId: undefined!,
isRedoing: false,
isUndoing: false,
});
assertOffsetAt(0, 1, 1);
@@ -179,6 +183,8 @@ suite('ExtHostDocumentData', () => {
}],
eol: undefined!,
versionId: undefined!,
isRedoing: false,
isUndoing: false,
});
assertOffsetAt(0, 1, 1);
@@ -197,6 +203,8 @@ suite('ExtHostDocumentData', () => {
}],
eol: undefined!,
versionId: undefined!,
isRedoing: false,
isUndoing: false,
});
assertOffsetAt(0, 1, 1);
@@ -218,6 +226,8 @@ suite('ExtHostDocumentData', () => {
}],
eol: undefined!,
versionId: undefined!,
isRedoing: false,
isUndoing: false,
});
assertOffsetAt(0, 1, 1);
@@ -398,6 +408,8 @@ suite('ExtHostDocumentData updates line mapping', () => {
}],
eol: eol!,
versionId: undefined!,
isRedoing: false,
isUndoing: false,
};
}
@@ -423,7 +435,7 @@ suite('ExtHostDocumentData updates line mapping', () => {
'and this is line number two',
'it is followed by #3',
'and finished with the fourth.',
], { changes: [], eol: undefined!, versionId: 7 });
], { changes: [], eol: undefined!, versionId: 7, isRedoing: false, isUndoing: false });
});
test('after remove', () => {

View File

@@ -306,7 +306,9 @@ suite('ExtHostDocumentSaveParticipant', () => {
text: 'bar'
}],
eol: undefined!,
versionId: 2
versionId: 2,
isRedoing: false,
isUndoing: false,
}, true);
e.waitUntil(Promise.resolve([TextEdit.insert(new Position(0, 0), 'bar')]));
@@ -338,7 +340,9 @@ suite('ExtHostDocumentSaveParticipant', () => {
rangeLength: undefined!,
}],
eol: undefined!,
versionId: documents.getDocumentData(uri)!.version + 1
versionId: documents.getDocumentData(uri)!.version + 1,
isRedoing: false,
isUndoing: false,
}, true);
// }
}

View File

@@ -23,6 +23,7 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
import { generateUuid } from 'vs/base/common/uuid';
import { Event } from 'vs/base/common/event';
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
suite('NotebookCell#Document', function () {
@@ -63,7 +64,7 @@ suite('NotebookCell#Document', function () {
let reg = extHostNotebooks.registerNotebookContentProvider(nullExtensionDescription, 'test', new class extends mock<vscode.NotebookContentProvider>() {
// async openNotebook() { }
});
extHostNotebooks.$acceptDocumentAndEditorsDelta({
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({
addedDocuments: [{
uri: notebookUri,
viewType: 'test',
@@ -92,8 +93,8 @@ suite('NotebookCell#Document', function () {
selections: [{ start: 0, end: 1 }],
visibleRanges: []
}]
});
extHostNotebooks.$acceptDocumentAndEditorsDelta({ newActiveEditor: '_notebook_editor_0' });
}));
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({ newActiveEditor: '_notebook_editor_0' }));
notebook = extHostNotebooks.notebookDocuments[0]!;
@@ -134,7 +135,7 @@ suite('NotebookCell#Document', function () {
removedCellUris.push(doc.uri.toString());
});
extHostNotebooks.$acceptDocumentAndEditorsDelta({ removedDocuments: [notebook.uri] });
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({ removedDocuments: [notebook.uri] }));
reg.dispose();
assert.strictEqual(removedCellUris.length, 2);
@@ -167,7 +168,7 @@ suite('NotebookCell#Document', function () {
});
});
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -191,7 +192,7 @@ suite('NotebookCell#Document', function () {
}]]]
}
]
}, false);
}), false);
await p;
@@ -229,7 +230,7 @@ suite('NotebookCell#Document', function () {
}
// close notebook -> docs are closed
extHostNotebooks.$acceptDocumentAndEditorsDelta({ removedDocuments: [notebook.uri] });
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({ removedDocuments: [notebook.uri] }));
for (let cell of notebook.apiNotebook.getCells()) {
assert.throws(() => extHostDocuments.getDocument(cell.document.uri));
}
@@ -243,7 +244,7 @@ suite('NotebookCell#Document', function () {
assert.strictEqual(notebook.apiNotebook.cellCount, 2);
const [cell1, cell2] = notebook.apiNotebook.getCells();
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, new SerializableObjectWithBuffers({
versionId: 2,
rawEvents: [
{
@@ -251,7 +252,7 @@ suite('NotebookCell#Document', function () {
changes: [[0, 1, []]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1);
assert.strictEqual(cell1.document.isClosed, true); // ref still alive!
@@ -274,18 +275,18 @@ suite('NotebookCell#Document', function () {
assert.strictEqual(second.index, 1);
// remove first cell
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 1, []]]
}]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1);
assert.strictEqual(second.index, 0);
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
@@ -307,7 +308,7 @@ suite('NotebookCell#Document', function () {
outputs: [],
}]]]
}]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 3);
assert.strictEqual(second.index, 2);
@@ -320,7 +321,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);
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, new SerializableObjectWithBuffers({
versionId: 100,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
@@ -342,7 +343,7 @@ suite('NotebookCell#Document', function () {
outputs: [],
}]]]
}]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 2);
@@ -363,18 +364,18 @@ suite('NotebookCell#Document', function () {
let count = 0;
extHostNotebooks.onDidChangeActiveNotebookEditor(() => count += 1);
extHostNotebooks.$acceptDocumentAndEditorsDelta({
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({
addedEditors: [{
documentUri: notebookUri,
id: '_notebook_editor_2',
selections: [{ start: 0, end: 1 }],
visibleRanges: []
}]
});
}));
extHostNotebooks.$acceptDocumentAndEditorsDelta({
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({
newActiveEditor: '_notebook_editor_2'
});
}));
assert.strictEqual(count, 1);
});
@@ -384,13 +385,13 @@ suite('NotebookCell#Document', function () {
const editor = extHostNotebooks.activeNotebookEditor;
assert.ok(editor !== undefined);
extHostNotebooks.$acceptDocumentAndEditorsDelta({ newActiveEditor: undefined });
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({ newActiveEditor: undefined }));
assert.ok(extHostNotebooks.activeNotebookEditor === editor);
extHostNotebooks.$acceptDocumentAndEditorsDelta({});
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({}));
assert.ok(extHostNotebooks.activeNotebookEditor === editor);
extHostNotebooks.$acceptDocumentAndEditorsDelta({ newActiveEditor: null });
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({ newActiveEditor: null }));
assert.ok(extHostNotebooks.activeNotebookEditor === undefined);
});
@@ -403,13 +404,13 @@ suite('NotebookCell#Document', function () {
const removed = Event.toPromise(extHostDocuments.onDidRemoveDocument);
const added = Event.toPromise(extHostDocuments.onDidAddDocument);
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, new SerializableObjectWithBuffers({
versionId: 12, rawEvents: [{
kind: NotebookCellsChangeType.ChangeLanguage,
index: 0,
language: 'fooLang'
}]
}, false);
}), false);
const removedDoc = await removed;
const addedDoc = await added;

View File

@@ -23,6 +23,7 @@ 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';
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
suite('NotebookConcatDocument', function () {
@@ -60,7 +61,7 @@ suite('NotebookConcatDocument', function () {
let reg = extHostNotebooks.registerNotebookContentProvider(nullExtensionDescription, 'test', new class extends mock<vscode.NotebookContentProvider>() {
// async openNotebook() { }
});
extHostNotebooks.$acceptDocumentAndEditorsDelta({
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({
addedDocuments: [{
uri: notebookUri,
viewType: 'test',
@@ -81,8 +82,8 @@ suite('NotebookConcatDocument', function () {
selections: [{ start: 0, end: 1 }],
visibleRanges: []
}]
});
extHostNotebooks.$acceptDocumentAndEditorsDelta({ newActiveEditor: '_notebook_editor_0' });
}));
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({ newActiveEditor: '_notebook_editor_0' }));
notebook = extHostNotebooks.notebookDocuments[0]!;
@@ -127,7 +128,7 @@ suite('NotebookConcatDocument', function () {
const cellUri1 = CellUri.generate(notebook.uri, 1);
const cellUri2 = CellUri.generate(notebook.uri, 2);
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
@@ -150,7 +151,7 @@ suite('NotebookConcatDocument', function () {
}]]
]
}]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 2); // markdown and code
@@ -164,7 +165,7 @@ suite('NotebookConcatDocument', function () {
test('location, position mapping', function () {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -188,7 +189,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 2); // markdown and code
@@ -209,7 +210,7 @@ suite('NotebookConcatDocument', function () {
let doc = new ExtHostNotebookConcatDocument(extHostNotebooks, extHostDocuments, notebook.apiNotebook, undefined);
// UPDATE 1
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -225,7 +226,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 1);
assert.strictEqual(doc.version, 1);
assertLines(doc, 'Hello', 'World', 'Hello World!');
@@ -236,7 +237,7 @@ suite('NotebookConcatDocument', function () {
// UPDATE 2
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -252,7 +253,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 2);
assert.strictEqual(doc.version, 2);
@@ -264,7 +265,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)
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -272,7 +273,7 @@ suite('NotebookConcatDocument', function () {
changes: [[1, 1, []]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 1);
assert.strictEqual(doc.version, 3);
assertLines(doc, 'Hello', 'World', 'Hello World!');
@@ -286,7 +287,7 @@ suite('NotebookConcatDocument', function () {
let doc = new ExtHostNotebookConcatDocument(extHostNotebooks, extHostDocuments, notebook.apiNotebook, undefined);
// UPDATE 1
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -311,7 +312,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 2);
assert.strictEqual(doc.version, 1);
@@ -334,7 +335,9 @@ suite('NotebookConcatDocument', function () {
rangeLength: 6,
rangeOffset: 12,
text: 'Hi'
}]
}],
isRedoing: false,
isUndoing: false,
}, false);
assertLines(doc, 'Hello', 'World', 'Hi World!', 'Hallo', 'Welt', 'Hallo Welt!');
assertLocation(doc, new Position(2, 12), new Location(notebook.apiNotebook.cellAt(0).document.uri, new Position(2, 9)), false);
@@ -345,7 +348,7 @@ suite('NotebookConcatDocument', function () {
test('selector', function () {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -369,7 +372,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
const mixedDoc = new ExtHostNotebookConcatDocument(extHostNotebooks, extHostDocuments, notebook.apiNotebook, undefined);
const fooLangDoc = new ExtHostNotebookConcatDocument(extHostNotebooks, extHostDocuments, notebook.apiNotebook, 'fooLang');
@@ -379,7 +382,7 @@ suite('NotebookConcatDocument', function () {
assertLines(fooLangDoc, 'fooLang-document');
assertLines(barLangDoc, 'barLang-document');
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -395,7 +398,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
assertLines(mixedDoc, 'fooLang-document', 'barLang-document', 'barLang-document2');
assertLines(fooLangDoc, 'fooLang-document');
@@ -417,7 +420,7 @@ suite('NotebookConcatDocument', function () {
test('offsetAt(position) <-> positionAt(offset)', function () {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -441,7 +444,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 2); // markdown and code
@@ -474,7 +477,7 @@ suite('NotebookConcatDocument', function () {
test('locationAt(position) <-> positionAt(location)', function () {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -498,7 +501,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 2); // markdown and code
@@ -515,7 +518,7 @@ suite('NotebookConcatDocument', function () {
test('getText(range)', function () {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -536,24 +539,33 @@ suite('NotebookConcatDocument', function () {
language: 'test',
cellKind: CellKind.Code,
outputs: [],
}, {
handle: 3,
uri: CellUri.generate(notebook.uri, 3),
source: ['Three', 'Drei', 'Drüü'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
}]]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 2); // markdown and code
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 3); // markdown and code
let doc = new ExtHostNotebookConcatDocument(extHostNotebooks, extHostDocuments, notebook.apiNotebook, undefined);
assertLines(doc, 'Hello', 'World', 'Hello World!', 'Hallo', 'Welt', 'Hallo Welt!');
assertLines(doc, 'Hello', 'World', 'Hello World!', 'Hallo', 'Welt', 'Hallo Welt!', 'Three', 'Drei', 'Drüü');
assert.strictEqual(doc.getText(new Range(0, 0, 0, 0)), '');
assert.strictEqual(doc.getText(new Range(0, 0, 1, 0)), 'Hello\n');
assert.strictEqual(doc.getText(new Range(2, 0, 4, 0)), 'Hello World!\nHallo\n');
assert.strictEqual(doc.getText(new Range(2, 0, 8, 0)), 'Hello World!\nHallo\nWelt\nHallo Welt!\nThree\nDrei\n');
});
test('validateRange/Position', function () {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, {
extHostNotebookDocuments.$acceptModelChanged(notebookUri, new SerializableObjectWithBuffers({
versionId: notebook.apiNotebook.version + 1,
rawEvents: [
{
@@ -577,7 +589,7 @@ suite('NotebookConcatDocument', function () {
}]]]
}
]
}, false);
}), false);
assert.strictEqual(notebook.apiNotebook.cellCount, 1 + 2); // markdown and code

View File

@@ -4,27 +4,31 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
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, 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 { Barrier } from 'vs/base/common/async';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { NullLogService } from 'vs/platform/log/common/log';
import { ICellExecuteUpdateDto, INotebookKernelDto2, MainContext, MainThreadCommandsShape, MainThreadNotebookDocumentsShape, MainThreadNotebookKernelsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
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 { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
import { ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
import { ExtHostNotebookKernels } from 'vs/workbench/api/common/extHostNotebookKernels';
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
import { NotebookCellOutput, NotebookCellOutputItem } from 'vs/workbench/api/common/extHostTypes';
import { CellKind, CellUri, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellExecutionUpdateType } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
suite('NotebookKernel', function () {
suite.skip('NotebookKernel', function () { // {{SQL CARBON EDIT}} Skip failing VS Notebook tests since we don't use their stuff
let rpcProtocol: TestRPCProtocol;
let extHostNotebookKernels: ExtHostNotebookKernels;
@@ -38,11 +42,13 @@ suite('NotebookKernel', function () {
const kernelData = new Map<number, INotebookKernelDto2>();
const disposables = new DisposableStore();
const cellExecuteUpdates: ICellExecuteUpdateDto[] = [];
teardown(function () {
disposables.clear();
});
setup(async function () {
cellExecuteUpdates.length = 0;
kernelData.clear();
rpcProtocol = new TestRPCProtocol();
@@ -60,9 +66,12 @@ suite('NotebookKernel', function () {
assert.strictEqual(kernelData.has(handle), true);
kernelData.set(handle, { ...kernelData.get(handle)!, ...data, });
}
override $updateExecutions(data: SerializableObjectWithBuffers<ICellExecuteUpdateDto[]>): void {
cellExecuteUpdates.push(...data.value);
}
});
rpcProtocol.set(MainContext.MainThreadNotebookDocuments, new class extends mock<MainThreadNotebookDocumentsShape>() {
override async $applyEdits() { }
});
rpcProtocol.set(MainContext.MainThreadNotebook, new class extends mock<MainThreadNotebookShape>() {
override async $registerNotebookProvider() { }
@@ -79,7 +88,7 @@ suite('NotebookKernel', function () {
extHostNotebookDocuments = new ExtHostNotebookDocuments(new NullLogService(), extHostNotebooks);
extHostNotebooks.$acceptDocumentAndEditorsDelta({
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({
addedDocuments: [{
uri: notebookUri,
viewType: 'test',
@@ -108,8 +117,8 @@ suite('NotebookKernel', function () {
selections: [{ start: 0, end: 1 }],
visibleRanges: []
}]
});
extHostNotebooks.$acceptDocumentAndEditorsDelta({ newActiveEditor: '_notebook_editor_0' });
}));
extHostNotebooks.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers({ newActiveEditor: '_notebook_editor_0' }));
notebook = extHostNotebooks.notebookDocuments[0]!;
@@ -198,13 +207,13 @@ suite('NotebookKernel', function () {
const cell1 = notebook.apiNotebook.cellAt(0);
extHostNotebookKernels.$acceptNotebookAssociation(0, notebook.uri, true);
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, {
extHostNotebookDocuments.$acceptModelChanged(notebook.uri, new SerializableObjectWithBuffers({
versionId: 12,
rawEvents: [{
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, notebook.apiNotebook.cellCount, []]]
}]
}, true);
}), true);
assert.strictEqual(cell1.index, -1);
@@ -235,4 +244,75 @@ suite('NotebookKernel', function () {
assert.strictEqual(interruptCallCount, 2);
assert.strictEqual(tokenCancelCount, 0);
});
test('set outputs on cancel', async 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();
const b = new Barrier();
task.token.onCancellationRequested(async () => {
await task.replaceOutput(new NotebookCellOutput([NotebookCellOutputItem.text('canceled')]));
task.end(true);
b.open(); // use barrier to signal that cancellation has happened
});
cellExecuteUpdates.length = 0;
await extHostNotebookKernels.$cancelCells(0, notebook.uri, [0]);
await b.wait();
assert.strictEqual(cellExecuteUpdates.length > 0, true);
let found = false;
for (let edit of cellExecuteUpdates) {
if (edit.editType === CellExecutionUpdateType.Output) {
assert.strictEqual(edit.append, false);
assert.strictEqual(edit.outputs.length, 1);
assert.strictEqual(edit.outputs[0].items.length, 1);
assert.deepStrictEqual(Array.from(edit.outputs[0].items[0].valueBytes.buffer), Array.from(new TextEncoder().encode('canceled')));
found = true;
}
}
assert.ok(found);
});
test('set outputs on interrupt', async 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();
kernel.interruptHandler = async _notebook => {
assert.ok(notebook.apiNotebook === _notebook);
await task.replaceOutput(new NotebookCellOutput([NotebookCellOutputItem.text('interrupted')]));
task.end(true);
};
cellExecuteUpdates.length = 0;
await extHostNotebookKernels.$cancelCells(0, notebook.uri, [0]);
assert.strictEqual(cellExecuteUpdates.length > 0, true);
let found = false;
for (let edit of cellExecuteUpdates) {
if (edit.editType === CellExecutionUpdateType.Output) {
assert.strictEqual(edit.append, false);
assert.strictEqual(edit.outputs.length, 1);
assert.strictEqual(edit.outputs[0].items.length, 1);
assert.deepStrictEqual(Array.from(edit.outputs[0].items[0].valueBytes.buffer), Array.from(new TextEncoder().encode('interrupted')));
found = true;
}
}
assert.ok(found);
});
});

View File

@@ -4,25 +4,28 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { CancellationToken } from 'vs/base/common/cancellation';
import { URI } from 'vs/base/common/uri';
import { createDefaultDocumentTestRoot, TestItemFilteredWrapper } from 'vs/workbench/api/common/extHostTesting';
import { VSBuffer } from 'vs/base/common/buffer';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { Iterable } from 'vs/base/common/iterator';
import { mockObject, MockObject } from 'vs/base/test/common/mock';
import { MainThreadTestingShape } from 'vs/workbench/api/common/extHost.protocol';
import { TestRunCoordinator, TestRunDto, TestRunProfileImpl } from 'vs/workbench/api/common/extHostTesting';
import * as convert from 'vs/workbench/api/common/extHostTypeConverters';
import { TestMessage, TestResultState, TestRunProfileKind, TestTag } from 'vs/workbench/api/common/extHostTypes';
import { TestDiffOpType, TestItemExpandState } from 'vs/workbench/contrib/testing/common/testCollection';
import { stubTest, TestItemImpl, testStubs } from 'vs/workbench/contrib/testing/common/testStubs';
import { TestOwnedTestCollection, TestSingleUseCollection } from 'vs/workbench/contrib/testing/test/common/ownedTestCollection';
import { TestItem, TextDocument } from 'vscode';
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
import { TestItemImpl, testStubs } from 'vs/workbench/contrib/testing/common/testStubs';
import { TestSingleUseCollection } from 'vs/workbench/contrib/testing/test/common/ownedTestCollection';
import type { TestItem, TestRunRequest } from 'vscode';
const simplify = (item: TestItem<unknown>) => ({
const simplify = (item: TestItem) => ({
id: item.id,
label: item.label,
uri: item.uri,
range: item.range,
runnable: item.runnable,
debuggable: item.debuggable,
});
const assertTreesEqual = (a: TestItem<unknown> | undefined, b: TestItem<unknown> | undefined) => {
const assertTreesEqual = (a: TestItemImpl | undefined, b: TestItemImpl | undefined) => {
if (!a) {
throw new assert.AssertionError({ message: 'Expected a to be defined', actual: a });
}
@@ -33,10 +36,10 @@ const assertTreesEqual = (a: TestItem<unknown> | undefined, b: TestItem<unknown>
assert.deepStrictEqual(simplify(a), simplify(b));
const aChildren = [...a.children.keys()].slice().sort();
const bChildren = [...b.children.keys()].slice().sort();
const aChildren = [...a.children].map(c => c.id).sort();
const bChildren = [...b.children].map(c => c.id).sort();
assert.strictEqual(aChildren.length, bChildren.length, `expected ${a.label}.children.length == ${b.label}.children.length`);
aChildren.forEach(key => assertTreesEqual(a.children.get(key), b.children.get(key)));
aChildren.forEach(key => assertTreesEqual(a.children.get(key) as TestItemImpl, b.children.get(key) as TestItemImpl));
};
// const assertTreeListEqual = (a: ReadonlyArray<TestItem>, b: ReadonlyArray<TestItem>) => {
@@ -59,114 +62,254 @@ const assertTreesEqual = (a: TestItem<unknown> | undefined, b: TestItem<unknown>
suite('ExtHost Testing', () => {
let single: TestSingleUseCollection;
let owned: TestOwnedTestCollection;
setup(() => {
owned = new TestOwnedTestCollection();
single = owned.createForHierarchy(d => single.setDiff(d /* don't clear during testing */));
single = testStubs.nested();
single.onDidGenerateDiff(d => single.setDiff(d /* don't clear during testing */));
});
teardown(() => {
single.dispose();
assert.strictEqual(!owned.idToInternal?.size, true, 'expected owned ids to be empty after dispose');
});
suite('OwnedTestCollection', () => {
test('adds a root recursively', () => {
const tests = testStubs.nested();
single.addRoot(tests, 'pid');
single.expand('id-root', Infinity);
test('adds a root recursively', async () => {
await single.expand(single.root.id, Infinity);
const a = single.root.children.get('id-a') as TestItemImpl;
const b = single.root.children.get('id-b') as TestItemImpl;
assert.deepStrictEqual(single.collectDiff(), [
[
TestDiffOpType.Add,
{ src: { tree: 0, controller: 'pid' }, parent: null, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(stubTest('root')) } }
{ controllerId: 'ctrlId', parent: null, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(single.root) } }
],
[
TestDiffOpType.Add,
{ src: { tree: 0, controller: 'pid' }, parent: 'id-root', expand: TestItemExpandState.Expandable, item: { ...convert.TestItem.from(stubTest('a')) } }
{ controllerId: 'ctrlId', parent: single.root.id, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(a) } }
],
[
TestDiffOpType.Add,
{ src: { tree: 0, controller: 'pid' }, parent: 'id-root', expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(stubTest('b')) }
{ controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-aa') as TestItemImpl) }
],
[
TestDiffOpType.Add,
{ controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-ab') as TestItemImpl) }
],
[
TestDiffOpType.Update,
{ extId: 'id-root', expand: TestItemExpandState.Expanded }
],
[
TestDiffOpType.Update,
{ extId: 'id-a', expand: TestItemExpandState.BusyExpanding }
{ extId: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.Expanded }
],
[
TestDiffOpType.Add,
{ src: { tree: 0, controller: 'pid' }, parent: 'id-a', expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(stubTest('aa')) }
],
[
TestDiffOpType.Add,
{ src: { tree: 0, controller: 'pid' }, parent: 'id-a', expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(stubTest('ab')) }
{ controllerId: 'ctrlId', parent: single.root.id, expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b) }
],
[
TestDiffOpType.Update,
{ extId: 'id-a', expand: TestItemExpandState.Expanded }
{ extId: single.root.id, expand: TestItemExpandState.Expanded }
],
]);
});
test('parents are set correctly', () => {
single.expand(single.root.id, Infinity);
single.collectDiff();
const a = single.root.children.get('id-a')!;
const ab = a.children.get('id-ab')!;
assert.strictEqual(a.parent, undefined);
assert.strictEqual(ab.parent, a);
});
test('no-ops if items not changed', () => {
const tests = testStubs.nested();
single.addRoot(tests, 'pid');
single.collectDiff();
assert.deepStrictEqual(single.collectDiff(), []);
});
test('watches property mutations', () => {
const tests = testStubs.nested();
single.addRoot(tests, 'pid');
single.expand('id-root', Infinity);
single.expand(single.root.id, Infinity);
single.collectDiff();
tests.children.get('id-a')!.description = 'Hello world'; /* item a */
single.root.children.get('id-a')!.description = 'Hello world'; /* item a */
assert.deepStrictEqual(single.collectDiff(), [
[
TestDiffOpType.Update,
{ extId: 'id-a', item: { description: 'Hello world' } }],
{ extId: new TestId(['ctrlId', 'id-a']).toString(), item: { description: 'Hello world' } }],
]);
});
test('removes children', () => {
const tests = testStubs.nested();
single.addRoot(tests, 'pid');
single.expand('id-root', Infinity);
single.expand(single.root.id, Infinity);
single.collectDiff();
tests.children.get('id-a')!.dispose();
single.root.children.delete('id-a');
assert.deepStrictEqual(single.collectDiff(), [
[TestDiffOpType.Remove, 'id-a'],
[TestDiffOpType.Remove, new TestId(['ctrlId', 'id-a']).toString()],
]);
assert.deepStrictEqual([...owned.idToInternal].map(n => n.item.extId).sort(), ['id-b', 'id-root']);
assert.strictEqual(single.itemToInternal.size, 2);
assert.deepStrictEqual(
[...single.tree.keys()].sort(),
[single.root.id, new TestId(['ctrlId', 'id-b']).toString()],
);
assert.strictEqual(single.tree.size, 2);
});
test('adds new children', () => {
const tests = testStubs.nested();
single.addRoot(tests, 'pid');
single.expand('id-root', Infinity);
single.expand(single.root.id, Infinity);
single.collectDiff();
const child = stubTest('ac');
tests.children.get('id-a')!.addChild(child);
const child = new TestItemImpl('ctrlId', 'id-ac', 'c', undefined);
single.root.children.get('id-a')!.children.add(child);
assert.deepStrictEqual(single.collectDiff(), [
[TestDiffOpType.Add, {
src: { tree: 0, controller: 'pid' },
parent: 'id-a',
controllerId: 'ctrlId',
parent: new TestId(['ctrlId', 'id-a']).toString(),
expand: TestItemExpandState.NotExpandable,
item: convert.TestItem.from(child),
}],
]);
assert.deepStrictEqual(
[...owned.idToInternal].map(n => n.item.extId).sort(),
['id-a', 'id-aa', 'id-ab', 'id-ac', 'id-b', 'id-root'],
[...single.tree.values()].map(n => n.actual.id).sort(),
[single.root.id, 'id-a', 'id-aa', 'id-ab', 'id-ac', 'id-b'],
);
assert.strictEqual(single.itemToInternal.size, 6);
assert.strictEqual(single.tree.size, 6);
});
test('manages tags correctly', () => {
single.expand(single.root.id, Infinity);
single.collectDiff();
const tag1 = new TestTag('tag1', 'Tag 1');
const tag2 = new TestTag('tag2', 'Tag 2');
const tag3 = new TestTag('tag3');
const child = new TestItemImpl('ctrlId', 'id-ac', 'c', undefined);
child.tags = [tag1, tag2];
single.root.children.get('id-a')!.children.add(child);
assert.deepStrictEqual(single.collectDiff(), [
[TestDiffOpType.AddTag, { ctrlLabel: 'root', id: 'ctrlId\0tag1', label: 'Tag 1' }],
[TestDiffOpType.AddTag, { ctrlLabel: 'root', id: 'ctrlId\0tag2', label: 'Tag 2' }],
[TestDiffOpType.Add, {
controllerId: 'ctrlId',
parent: new TestId(['ctrlId', 'id-a']).toString(),
expand: TestItemExpandState.NotExpandable,
item: convert.TestItem.from(child),
}],
]);
child.tags = [tag2, tag3];
assert.deepStrictEqual(single.collectDiff(), [
[TestDiffOpType.AddTag, { ctrlLabel: 'root', id: 'ctrlId\0tag3', label: undefined }],
[TestDiffOpType.Update, {
extId: new TestId(['ctrlId', 'id-a', 'id-ac']).toString(),
item: { tags: ['ctrlId\0tag2', 'ctrlId\0tag3'] }
}],
[TestDiffOpType.RemoveTag, 'ctrlId\0tag1'],
]);
const a = single.root.children.get('id-a')!;
a.tags = [tag2];
a.children.replace([]);
assert.deepStrictEqual(single.collectDiff().filter(t => t[0] === TestDiffOpType.RemoveTag), [
[TestDiffOpType.RemoveTag, 'ctrlId\0tag3'],
]);
});
test('treats in-place replacement as mutation', () => {
single.expand(single.root.id, Infinity);
single.collectDiff();
const oldA = single.root.children.get('id-a') as TestItemImpl;
const newA = new TestItemImpl('ctrlId', 'id-a', 'Hello world', undefined);
newA.children.replace([...oldA.children]);
single.root.children.replace([
newA,
new TestItemImpl('ctrlId', 'id-b', single.root.children.get('id-b')!.label, undefined),
]);
assert.deepStrictEqual(single.collectDiff(), [
[
TestDiffOpType.Update,
{ extId: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.Expanded, item: { label: 'Hello world' } },
],
]);
newA.label = 'still connected';
assert.deepStrictEqual(single.collectDiff(), [
[
TestDiffOpType.Update,
{ extId: new TestId(['ctrlId', 'id-a']).toString(), item: { label: 'still connected' } }
],
]);
oldA.label = 'no longer connected';
assert.deepStrictEqual(single.collectDiff(), []);
});
test('treats in-place replacement as mutation deeply', () => {
single.expand(single.root.id, Infinity);
single.collectDiff();
const oldA = single.root.children.get('id-a')!;
const newA = new TestItemImpl('ctrlId', 'id-a', single.root.children.get('id-a')!.label, undefined);
const oldAA = oldA.children.get('id-aa')!;
const oldAB = oldA.children.get('id-ab')!;
const newAB = new TestItemImpl('ctrlId', 'id-ab', 'Hello world', undefined);
newA.children.replace([oldAA, newAB]);
single.root.children.replace([newA, single.root.children.get('id-b')!]);
assert.deepStrictEqual(single.collectDiff(), [
[
TestDiffOpType.Update,
{ extId: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.Expanded },
],
[
TestDiffOpType.Update,
{ extId: TestId.fromExtHostTestItem(oldAB, 'ctrlId').toString(), item: { label: 'Hello world' } },
],
]);
oldAA.label = 'still connected1';
newAB.label = 'still connected2';
oldAB.label = 'not connected3';
assert.deepStrictEqual(single.collectDiff(), [
[
TestDiffOpType.Update,
{ extId: new TestId(['ctrlId', 'id-a', 'id-aa']).toString(), item: { label: 'still connected1' } }
],
[
TestDiffOpType.Update,
{ extId: new TestId(['ctrlId', 'id-a', 'id-ab']).toString(), item: { label: 'still connected2' } }
],
]);
assert.strictEqual(newAB.parent, newA);
assert.strictEqual(oldAA.parent, newA);
assert.deepStrictEqual(newA.parent, undefined);
});
test('moves an item to be a new child', async () => {
await single.expand(single.root.id, 0);
single.collectDiff();
const b = single.root.children.get('id-b') as TestItemImpl;
const a = single.root.children.get('id-a') as TestItemImpl;
a.children.add(b);
assert.deepStrictEqual(single.collectDiff(), [
[
TestDiffOpType.Remove,
new TestId(['ctrlId', 'id-b']).toString(),
],
[
TestDiffOpType.Add,
{ controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b) }
],
]);
b.label = 'still connected';
assert.deepStrictEqual(single.collectDiff(), [
[
TestDiffOpType.Update,
{ extId: new TestId(['ctrlId', 'id-a', 'id-b']).toString(), item: { label: 'still connected' } }
],
]);
assert.deepStrictEqual([...single.root.children], [single.root.children.get('id-a')]);
assert.deepStrictEqual(b.parent, a);
});
});
@@ -179,9 +322,9 @@ suite('ExtHost Testing', () => {
// test('mirrors creation of the root', () => {
// const tests = testStubs.nested();
// single.addRoot(tests, 'pid');
// single.expand('id-root', Infinity);
// single.expand(single.root.id, Infinity);
// m.apply(single.collectDiff());
// assertTreesEqual(m.rootTestItems[0], owned.getTestById('id-root')![1].actual);
// assertTreesEqual(m.rootTestItems[0], owned.getTestById(single.root.id)![1].actual);
// assert.strictEqual(m.length, single.itemToInternal.size);
// });
@@ -189,13 +332,13 @@ suite('ExtHost Testing', () => {
// const tests = testStubs.nested();
// single.addRoot(tests, 'pid');
// m.apply(single.collectDiff());
// single.expand('id-root', Infinity);
// single.expand(single.root.id, Infinity);
// tests.children!.splice(0, 1);
// single.onItemChange(tests, 'pid');
// single.expand('id-root', Infinity);
// single.expand(single.root.id, Infinity);
// m.apply(single.collectDiff());
// assertTreesEqual(m.rootTestItems[0], owned.getTestById('id-root')![1].actual);
// assertTreesEqual(m.rootTestItems[0], owned.getTestById(single.root.id)![1].actual);
// assert.strictEqual(m.length, single.itemToInternal.size);
// });
@@ -207,7 +350,7 @@ suite('ExtHost Testing', () => {
// single.onItemChange(tests, 'pid');
// m.apply(single.collectDiff());
// assertTreesEqual(m.rootTestItems[0], owned.getTestById('id-root')![1].actual);
// assertTreesEqual(m.rootTestItems[0], owned.getTestById(single.root.id)![1].actual);
// assert.strictEqual(m.length, single.itemToInternal.size);
// });
@@ -219,7 +362,7 @@ suite('ExtHost Testing', () => {
// single.onItemChange(tests, 'pid');
// m.apply(single.collectDiff());
// assertTreesEqual(m.rootTestItems[0], owned.getTestById('id-root')![1].actual);
// assertTreesEqual(m.rootTestItems[0], owned.getTestById(single.root.id)![1].actual);
// });
// suite('MirroredChangeCollector', () => {
@@ -305,122 +448,161 @@ suite('ExtHost Testing', () => {
// m.apply(single.collectDiff());
// });
// });
});
suite('TestItemFilteredWrapper', () => {
const textDocumentFilter = {
uri: URI.parse('file:///foo.ts'),
} as TextDocument;
suite('TestRunTracker', () => {
let proxy: MockObject<MainThreadTestingShape>;
let c: TestRunCoordinator;
let cts: CancellationTokenSource;
let configuration: TestRunProfileImpl;
let testsWithLocation: TestItemImpl;
setup(async () => {
testsWithLocation =
stubTest('root', undefined, [
stubTest('a', undefined, [
stubTest('aa', undefined, undefined, URI.parse('file:///foo.ts')),
stubTest('ab', undefined, undefined, URI.parse('file:///foo.ts'))
], URI.parse('file:///foo.ts')),
stubTest('b', undefined, [
stubTest('ba', undefined, undefined, URI.parse('file:///bar.ts')),
stubTest('bb', undefined, undefined, URI.parse('file:///bar.ts'))
], URI.parse('file:///bar.ts')),
stubTest('c', undefined, undefined, URI.parse('file:///baz.ts')),
]);
let req: TestRunRequest;
// todo: this is not used, don't think it's needed anymore
await createDefaultDocumentTestRoot<void>(
{
createWorkspaceTestRoot: () => testsWithLocation as TestItem<void>,
runTests() {
throw new Error('no implemented');
}
},
textDocumentFilter,
undefined,
CancellationToken.None
);
});
let dto: TestRunDto;
teardown(() => {
TestItemFilteredWrapper.removeFilter(textDocumentFilter);
});
setup(async () => {
proxy = mockObject();
cts = new CancellationTokenSource();
c = new TestRunCoordinator(proxy);
test('gets all actual properties', () => {
const testItem = stubTest('test1');
const wrapper = TestItemFilteredWrapper.getWrapperForTestItem(testItem, textDocumentFilter);
configuration = new TestRunProfileImpl(mockObject<MainThreadTestingShape, {}>(), 'ctrlId', 42, 'Do Run', TestRunProfileKind.Run, () => { }, false);
assert.strictEqual(testItem.debuggable, wrapper.debuggable);
assert.strictEqual(testItem.description, wrapper.description);
assert.strictEqual(testItem.label, wrapper.label);
assert.strictEqual(testItem.uri, wrapper.uri);
assert.strictEqual(testItem.runnable, wrapper.runnable);
});
await single.expand(single.root.id, Infinity);
single.collectDiff();
test('gets no children if nothing matches Uri filter', () => {
const tests = testStubs.nested();
const wrapper = TestItemFilteredWrapper.getWrapperForTestItem(tests, textDocumentFilter);
wrapper.resolveHandler?.(CancellationToken.None);
assert.strictEqual(wrapper.children.size, 0);
});
req = {
include: undefined,
exclude: [single.root.children.get('id-b')!],
profile: configuration,
};
test('filter is applied to children', () => {
const wrapper = TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
assert.strictEqual(wrapper.label, 'root');
wrapper.resolveHandler?.(CancellationToken.None);
dto = TestRunDto.fromInternal({
controllerId: 'ctrl',
profileId: configuration.profileId,
excludeExtIds: ['id-b'],
runId: 'run-id',
testIds: [single.root.id],
}, single);
});
const children = [...wrapper.children.values()];
assert.strictEqual(children.length, 1);
assert.strictEqual(children[0] instanceof TestItemFilteredWrapper, true);
assert.strictEqual(children[0].label, 'a');
});
test('tracks a run started from a main thread request', () => {
const tracker = c.prepareForMainThreadTestRun(req, dto, cts.token);
assert.strictEqual(tracker.isRunning, false);
test('can get if node has matching filter', () => {
const rootWrapper = TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
rootWrapper.resolveHandler?.(CancellationToken.None);
const task1 = c.createTestRun('ctrl', single, req, 'run1', true);
const task2 = c.createTestRun('ctrl', single, req, 'run2', true);
assert.strictEqual(proxy.$startedExtensionTestRun.called, false);
assert.strictEqual(tracker.isRunning, true);
const invisible = testsWithLocation.children.get('id-b')!;
const invisibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisible, textDocumentFilter);
const visible = testsWithLocation.children.get('id-a')!;
const visibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(visible, textDocumentFilter);
task1.appendOutput('hello');
const taskId = proxy.$appendOutputToRun.args[0]?.[1];
assert.deepStrictEqual([['run-id', taskId, VSBuffer.fromString('hello'), undefined, undefined]], proxy.$appendOutputToRun.args);
task1.end();
// The root is always visible
assert.strictEqual(rootWrapper.hasNodeMatchingFilter, true);
assert.strictEqual(invisibleWrapper.hasNodeMatchingFilter, false);
assert.strictEqual(visibleWrapper.hasNodeMatchingFilter, true);
});
assert.strictEqual(proxy.$finishedExtensionTestRun.called, false);
assert.strictEqual(tracker.isRunning, true);
test('can reset cached value of hasNodeMatchingFilter', () => {
const wrapper = TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
wrapper.resolveHandler?.(CancellationToken.None);
task2.end();
const invisible = testsWithLocation.children.get('id-b')!;
const invisibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisible, textDocumentFilter);
assert.strictEqual(proxy.$finishedExtensionTestRun.called, false);
assert.strictEqual(tracker.isRunning, false);
});
assert.strictEqual(wrapper.children.get('id-b'), undefined);
assert.strictEqual(invisibleWrapper.hasNodeMatchingFilter, false);
test('tracks a run started from an extension request', () => {
const task1 = c.createTestRun('ctrl', single, req, 'hello world', false);
invisible.addChild(stubTest('bc', undefined, undefined, URI.parse('file:///foo.ts')));
assert.strictEqual(invisibleWrapper.hasNodeMatchingFilter, true);
assert.strictEqual(invisibleWrapper.children.size, 1);
assert.strictEqual(wrapper.children.get('id-b'), invisibleWrapper);
});
const tracker = Iterable.first(c.trackers)!;
assert.strictEqual(tracker.isRunning, true);
assert.deepStrictEqual(proxy.$startedExtensionTestRun.args, [
[{
profile: { group: 2, id: 42 },
controllerId: 'ctrl',
id: tracker.id,
include: [single.root.id],
exclude: ['id-b'],
persist: false,
}]
]);
// test('can reset cached value of hasNodeMatchingFilter of parents up to visible parent', () => {
// const rootWrapper = TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
const task2 = c.createTestRun('ctrl', single, req, 'run2', true);
const task3Detached = c.createTestRun('ctrl', single, { ...req }, 'task3Detached', true);
// const invisibleParent = testsWithLocation.children.get('id-b')!;
// const invisibleParentWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisibleParent, textDocumentFilter);
// const invisible = invisibleParent.children.get('id-bb')!;
// const invisibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisible, textDocumentFilter);
task1.end();
assert.strictEqual(proxy.$finishedExtensionTestRun.called, false);
assert.strictEqual(tracker.isRunning, true);
// assert.strictEqual(invisibleParentWrapper.hasNodeMatchingFilter, false);
// invisible.location = location1 as any;
// assert.strictEqual(invisibleParentWrapper.hasNodeMatchingFilter, false);
// invisibleWrapper.reset();
// assert.strictEqual(invisibleParentWrapper.hasNodeMatchingFilter, true);
task2.end();
assert.deepStrictEqual(proxy.$finishedExtensionTestRun.args, [[tracker.id]]);
assert.strictEqual(tracker.isRunning, false);
// // the root should be undefined due to the reset.
// assert.strictEqual((rootWrapper as any).matchesFilter, undefined);
// });
task3Detached.end();
});
test('adds tests to run smartly', () => {
const task1 = c.createTestRun('ctrl', single, req, 'hello world', false);
const tracker = Iterable.first(c.trackers)!;
const expectedArgs: unknown[][] = [];
assert.deepStrictEqual(proxy.$addTestsToRun.args, expectedArgs);
task1.passed(single.root.children.get('id-a')!.children.get('id-aa')!);
expectedArgs.push([
'ctrl',
tracker.id,
[
convert.TestItem.from(single.root),
convert.TestItem.from(single.root.children.get('id-a') as TestItemImpl),
convert.TestItem.from(single.root.children.get('id-a')!.children.get('id-aa') as TestItemImpl),
]
]);
assert.deepStrictEqual(proxy.$addTestsToRun.args, expectedArgs);
task1.enqueued(single.root.children.get('id-a')!.children.get('id-ab')!);
expectedArgs.push([
'ctrl',
tracker.id,
[
convert.TestItem.from(single.root.children.get('id-a') as TestItemImpl),
convert.TestItem.from(single.root.children.get('id-a')!.children.get('id-ab') as TestItemImpl),
],
]);
assert.deepStrictEqual(proxy.$addTestsToRun.args, expectedArgs);
task1.passed(single.root.children.get('id-a')!.children.get('id-ab')!);
assert.deepStrictEqual(proxy.$addTestsToRun.args, expectedArgs);
});
test('guards calls after runs are ended', () => {
const task = c.createTestRun('ctrl', single, req, 'hello world', false);
task.end();
task.failed(single.root, new TestMessage('some message'));
task.appendOutput('output');
assert.strictEqual(proxy.$addTestsToRun.called, false);
assert.strictEqual(proxy.$appendOutputToRun.called, false);
assert.strictEqual(proxy.$appendTestMessagesInRun.called, false);
});
test('excludes tests outside tree or explicitly excluded', () => {
const task = c.createTestRun('ctrlId', single, {
profile: configuration,
include: [single.root.children.get('id-a')!],
exclude: [single.root.children.get('id-a')!.children.get('id-aa')!],
}, 'hello world', false);
task.passed(single.root.children.get('id-a')!.children.get('id-aa')!);
task.passed(single.root.children.get('id-a')!.children.get('id-ab')!);
assert.deepStrictEqual(proxy.$updateTestStateInRun.args.length, 1);
const args = proxy.$updateTestStateInRun.args[0];
assert.deepStrictEqual(proxy.$updateTestStateInRun.args, [[
args[0],
args[1],
new TestId(['ctrlId', 'id-a', 'id-ab']).toString(),
TestResultState.Passed,
undefined,
]]);
});
});
});

View File

@@ -90,25 +90,25 @@ suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
test('construct node tree', () => {
return testObject.$getChildren('testNodeTreeProvider')
.then(elements => {
const actuals = elements.map(e => e.handle);
const actuals = elements?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['0/0:a', '0/0:b']);
return Promise.all([
testObject.$getChildren('testNodeTreeProvider', '0/0:a')
.then(children => {
const actuals = children.map(e => e.handle);
const actuals = children?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['0/0:a/0:aa', '0/0:a/0:ab']);
return Promise.all([
testObject.$getChildren('testNodeTreeProvider', '0/0:a/0:aa').then(children => assert.strictEqual(children.length, 0)),
testObject.$getChildren('testNodeTreeProvider', '0/0:a/0:ab').then(children => assert.strictEqual(children.length, 0))
testObject.$getChildren('testNodeTreeProvider', '0/0:a/0:aa').then(children => assert.strictEqual(children?.length, 0)),
testObject.$getChildren('testNodeTreeProvider', '0/0:a/0:ab').then(children => assert.strictEqual(children?.length, 0))
]);
}),
testObject.$getChildren('testNodeTreeProvider', '0/0:b')
.then(children => {
const actuals = children.map(e => e.handle);
const actuals = children?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['0/0:b/0:ba', '0/0:b/0:bb']);
return Promise.all([
testObject.$getChildren('testNodeTreeProvider', '0/0:b/0:ba').then(children => assert.strictEqual(children.length, 0)),
testObject.$getChildren('testNodeTreeProvider', '0/0:b/0:bb').then(children => assert.strictEqual(children.length, 0))
testObject.$getChildren('testNodeTreeProvider', '0/0:b/0:ba').then(children => assert.strictEqual(children?.length, 0)),
testObject.$getChildren('testNodeTreeProvider', '0/0:b/0:bb').then(children => assert.strictEqual(children?.length, 0))
]);
})
]);
@@ -118,25 +118,25 @@ suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
test('construct id tree', () => {
return testObject.$getChildren('testNodeWithIdTreeProvider')
.then(elements => {
const actuals = elements.map(e => e.handle);
const actuals = elements?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['1/a', '1/b']);
return Promise.all([
testObject.$getChildren('testNodeWithIdTreeProvider', '1/a')
.then(children => {
const actuals = children.map(e => e.handle);
const actuals = children?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['1/aa', '1/ab']);
return Promise.all([
testObject.$getChildren('testNodeWithIdTreeProvider', '1/aa').then(children => assert.strictEqual(children.length, 0)),
testObject.$getChildren('testNodeWithIdTreeProvider', '1/ab').then(children => assert.strictEqual(children.length, 0))
testObject.$getChildren('testNodeWithIdTreeProvider', '1/aa').then(children => assert.strictEqual(children?.length, 0)),
testObject.$getChildren('testNodeWithIdTreeProvider', '1/ab').then(children => assert.strictEqual(children?.length, 0))
]);
}),
testObject.$getChildren('testNodeWithIdTreeProvider', '1/b')
.then(children => {
const actuals = children.map(e => e.handle);
const actuals = children?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['1/ba', '1/bb']);
return Promise.all([
testObject.$getChildren('testNodeWithIdTreeProvider', '1/ba').then(children => assert.strictEqual(children.length, 0)),
testObject.$getChildren('testNodeWithIdTreeProvider', '1/bb').then(children => assert.strictEqual(children.length, 0))
testObject.$getChildren('testNodeWithIdTreeProvider', '1/ba').then(children => assert.strictEqual(children?.length, 0)),
testObject.$getChildren('testNodeWithIdTreeProvider', '1/bb').then(children => assert.strictEqual(children?.length, 0))
]);
})
]);
@@ -200,7 +200,7 @@ suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
target.onRefresh.event(() => {
testObject.$getChildren('testNodeWithIdTreeProvider')
.then(elements => {
const actuals = elements.map(e => e.handle);
const actuals = elements?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['1/a', '1/b']);
return testObject.$getChildren('testNodeWithIdTreeProvider', '1/a')
.then(() => testObject.$getChildren('testNodeWithIdTreeProvider', '1/b'))
@@ -398,7 +398,7 @@ suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
target.onRefresh.event(() => {
testObject.$getChildren('testNodeTreeProvider')
.then(elements => {
assert.deepStrictEqual(elements.map(e => e.handle), ['0/0:a//0:b']);
assert.deepStrictEqual(elements?.map(e => e.handle), ['0/0:a//0:b']);
done();
});
});
@@ -440,11 +440,11 @@ suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
target.onRefresh.event(() => {
testObject.$getChildren('testNodeTreeProvider')
.then(elements => {
const actuals = elements.map(e => e.handle);
const actuals = elements?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['0/0:a', '0/0:b', '0/1:a', '0/0:d', '0/1:b', '0/0:f', '0/2:a']);
return testObject.$getChildren('testNodeTreeProvider', '0/1:b')
.then(elements => {
const actuals = elements.map(e => e.handle);
const actuals = elements?.map(e => e.handle);
assert.deepStrictEqual(actuals, ['0/1:b/0:h', '0/1:b/1:h', '0/1:b/0:j', '0/1:b/1:j', '0/1:b/2:h']);
done();
});
@@ -462,7 +462,7 @@ suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
target.onRefresh.event(() => {
testObject.$getChildren('testNodeTreeProvider')
.then(elements => {
assert.deepStrictEqual(elements.map(e => e.handle), ['0/0:c']);
assert.deepStrictEqual(elements?.map(e => e.handle), ['0/0:c']);
done();
});
});
@@ -477,7 +477,7 @@ suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
return testObject.$getChildren('testNodeTreeProvider')
.then(elements => {
assert.deepStrictEqual(elements.map(e => e.handle), ['0/0:a', '0/0:b']);
assert.deepStrictEqual(elements?.map(e => e.handle), ['0/0:a', '0/0:b']);
});
});
@@ -643,7 +643,7 @@ suite.skip('ExtHostTreeView', function () { // {{SQL CARBON EDIT}} Skip suite
function loadCompleteTree(treeId: string, element?: string): Promise<null> {
return testObject.$getChildren(treeId, element)
.then(elements => elements.map(e => loadCompleteTree(treeId, e.handle)))
.then(elements => elements?.map(e => loadCompleteTree(treeId, e.handle)))
.then(() => null);
}

View File

@@ -104,11 +104,11 @@ suite('ExtHostTypeConverter', function () {
const dto = NotebookCellOutputItem.from(item);
assert.strictEqual(dto.mime, 'foo/bar');
assert.deepStrictEqual(dto.valueBytes, Array.from(new TextEncoder().encode('Hello')));
assert.deepStrictEqual(Array.from(dto.valueBytes.buffer), Array.from(new TextEncoder().encode('Hello')));
const item2 = NotebookCellOutputItem.to(dto);
assert.strictEqual(item2.mime, item.mime);
assert.deepStrictEqual(item2.data, item.data);
assert.deepStrictEqual(Array.from(item2.data), Array.from(item.data));
});
});

View File

@@ -8,6 +8,8 @@ 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 { Mimes } from 'vs/base/common/mime';
import { MarshalledId } from 'vs/base/common/marshalling';
function assertToJSON(a: any, expected: any) {
const raw = JSON.stringify(a);
@@ -21,14 +23,14 @@ suite('ExtHostTypes', function () {
let uri = URI.parse('file:///path/test.file');
assert.deepStrictEqual(uri.toJSON(), {
$mid: 1,
$mid: MarshalledId.Uri,
scheme: 'file',
path: '/path/test.file'
});
assert.ok(uri.fsPath);
assert.deepStrictEqual(uri.toJSON(), {
$mid: 1,
$mid: MarshalledId.Uri,
scheme: 'file',
path: '/path/test.file',
fsPath: '/path/test.file'.replace(/\//g, isWindows ? '\\' : '/'),
@@ -37,7 +39,7 @@ suite('ExtHostTypes', function () {
assert.ok(uri.toString());
assert.deepStrictEqual(uri.toJSON(), {
$mid: 1,
$mid: MarshalledId.Uri,
scheme: 'file',
path: '/path/test.file',
fsPath: '/path/test.file'.replace(/\//g, isWindows ? '\\' : '/'),
@@ -683,7 +685,7 @@ suite('ExtHostTypes', function () {
// --- text
item = types.NotebookCellOutputItem.text('Hęłlö');
assert.strictEqual(item.mime, 'text/plain');
assert.strictEqual(item.mime, Mimes.text);
assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö'));
item = types.NotebookCellOutputItem.text('Hęłlö', 'foo/bar');

View File

@@ -15,8 +15,8 @@ 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 { decodeAuthority, webviewResourceBaseHost } from 'vs/workbench/api/common/shared/webview';
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
import type * as vscode from 'vscode';
import { SingleProxyRPCProtocol } from './testRPCProtocol';
@@ -119,6 +119,29 @@ suite('ExtHostWebview', () => {
'Unix basic'
);
});
test('asWebviewUri for remote with / and + in name', () => {
const webview = createWebview(rpcProtocol, /* remoteAuthority */ 'remote');
const authority = 'ssh-remote+localhost=foo/bar';
const sourceUri = URI.from({
scheme: 'vscode-remote',
authority: authority,
path: '/Users/cody/x.png'
});
const webviewUri = webview.webview.asWebviewUri(sourceUri);
assert.strictEqual(
webviewUri.toString(),
`https://vscode-remote%2Bssh-002dremote-002blocalhost-003dfoo-002fbar.vscode-resource.vscode-webview.net/Users/cody/x.png`,
'Check transform');
assert.strictEqual(
decodeAuthority(webviewUri.authority),
`vscode-remote+${authority}.vscode-resource.vscode-webview.net`,
'Check decoded authority'
);
});
});
function createWebview(rpcProtocol: (IExtHostRpcService & IExtHostContext) | undefined, remoteAuthority: string | undefined) {

View File

@@ -27,7 +27,7 @@ import { FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
function createExtHostWorkspace(mainContext: IMainContext, data: IWorkspaceData, logService: ILogService): ExtHostWorkspace {
const result = new ExtHostWorkspace(
new ExtHostRpcService(mainContext),
new class extends mock<IExtHostInitDataService>() { workspace = data; },
new class extends mock<IExtHostInitDataService>() { override workspace = data; },
new class extends mock<IExtHostFileSystemInfo>() { override getCapabilities() { return isLinux ? FileSystemProviderCapabilities.PathCaseSensitive : undefined; } },
logService,
);

View File

@@ -0,0 +1,162 @@
/*---------------------------------------------------------------------------------------------
* 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 { AuthenticationProviderInformation } from 'vs/editor/common/modes';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { IQuickInputHideEvent, IQuickInputService, IQuickPickDidAcceptEvent } from 'vs/platform/quickinput/common/quickInput';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { MainThreadAuthentication } from 'vs/workbench/api/browser/mainThreadAuthentication';
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
import { AuthenticationService, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
import { ExtensionHostKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { TestRemoteAgentService } from 'vs/workbench/services/remote/test/common/testServices';
import { TestQuickInputService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestActivityService, TestExtensionService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
let i = 0;
function createSession(id: string = '1234', scope: string[] = []) {
return {
accessToken: (++i) + '',
account: {
id: 'test@test.com',
label: 'Test Person'
},
id: id,
scopes: scope
};
}
class AuthQuickPick {
private listener: ((e: IQuickPickDidAcceptEvent) => any) | undefined;
public items = [];
public get selectedItems(): string[] {
return this.items;
}
onDidAccept(listener: (e: IQuickPickDidAcceptEvent) => any) {
this.listener = listener;
}
onDidHide(listener: (e: IQuickInputHideEvent) => any) {
}
dispose() {
}
show() {
this.listener!({
inBackground: false
});
}
}
class AuthTestQuickInputService extends TestQuickInputService {
override createQuickPick() {
return <any>new AuthQuickPick();
}
}
suite('MainThreadAuthentication', () => {
let mainThreadAuthentication: MainThreadAuthentication;
let instantiationService: TestInstantiationService;
suiteSetup(async () => {
instantiationService = new TestInstantiationService();
// extHostContext: IExtHostContext,
instantiationService.stub(IDialogService, new TestDialogService());
instantiationService.stub(IStorageService, new TestStorageService());
instantiationService.stub(IQuickInputService, new AuthTestQuickInputService());
instantiationService.stub(IExtensionService, new TestExtensionService());
instantiationService.stub(IActivityService, new TestActivityService());
instantiationService.stub(IRemoteAgentService, new TestRemoteAgentService());
instantiationService.stub(INotificationService, new TestNotificationService());
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(IAuthenticationService, instantiationService.createInstance(AuthenticationService));
mainThreadAuthentication = instantiationService.createInstance(MainThreadAuthentication,
new class implements IExtHostContext {
remoteAuthority = '';
extensionHostKind = ExtensionHostKind.LocalProcess;
assertRegistered() { }
set(v: any): any { return null; }
getProxy(): any {
return {
async $getSessions(id: string, scopes: string[]) {
// if we get the empty auth provider, return no sessions
return id === 'empty' ? [] : [createSession(id, scopes)];
},
$createSession(id: string, scopes: string[]) {
return Promise.resolve(createSession(id, scopes));
},
$removeSession(id: string, sessionId: string) { return Promise.resolve(); },
$onDidChangeAuthenticationSessions(id: string, label: string) { return Promise.resolve(); },
$setProviders(providers: AuthenticationProviderInformation[]) { return Promise.resolve(); }
};
}
drain(): any { return null; }
});
});
setup(async () => {
await mainThreadAuthentication.$registerAuthenticationProvider('test', 'test provider', true);
await mainThreadAuthentication.$registerAuthenticationProvider('empty', 'test provider', true);
});
teardown(() => {
mainThreadAuthentication.$unregisterAuthenticationProvider('test');
mainThreadAuthentication.$unregisterAuthenticationProvider('empty');
});
test('Can get a session', async () => {
const session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', {
createIfNone: true,
clearSessionPreference: false,
forceNewSession: false
});
assert.strictEqual(session?.id, 'test');
assert.strictEqual(session?.scopes[0], 'foo');
});
test('Can recreate a session', async () => {
const session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', {
createIfNone: true,
clearSessionPreference: false,
forceNewSession: false
});
assert.strictEqual(session?.id, 'test');
assert.strictEqual(session?.scopes[0], 'foo');
const session2 = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', {
createIfNone: false,
clearSessionPreference: false,
forceNewSession: true
});
assert.strictEqual(session.id, session2?.id);
assert.strictEqual(session.scopes[0], session2?.scopes[0]);
assert.notStrictEqual(session.accessToken, session2?.accessToken);
});
test('Can not recreate a session if none exists', async () => {
try {
await mainThreadAuthentication.$getSession('empty', ['foo'], 'testextension', 'test extension', {
createIfNone: false,
clearSessionPreference: false,
forceNewSession: true
});
assert.fail('should have thrown an Error.');
} catch (e) {
assert.strictEqual(e.message, 'No existing sessions found.');
}
});
});

View File

@@ -3,12 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import { ProxyIdentifier, SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import { CharCode } from 'vs/base/common/charCode';
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { isThenable } from 'vs/base/common/async';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions';
import { parseJsonAndRestoreBufferRefs, stringifyJsonWithBufferRefs } from 'vs/workbench/services/extensions/common/rpcProtocol';
export function SingleProxyRPCProtocol(thing: any): IExtHostContext & IExtHostRpcService {
return {
@@ -143,5 +144,15 @@ function simulateWireTransfer<T>(obj: T): T {
if (!obj) {
return obj;
}
return JSON.parse(JSON.stringify(obj));
if (Array.isArray(obj)) {
return obj.map(simulateWireTransfer) as any;
}
if (obj instanceof SerializableObjectWithBuffers) {
const { jsonString, referencedBuffers } = stringifyJsonWithBufferRefs(obj);
return parseJsonAndRestoreBufferRefs(jsonString, referencedBuffers, null);
} else {
return JSON.parse(JSON.stringify(obj));
}
}

View File

@@ -35,11 +35,10 @@ suite('Diff editor input', () => {
let diffInput = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input, otherInput, undefined);
assert.strictEqual(diffInput.originalInput, input);
assert.strictEqual(diffInput.modifiedInput, otherInput);
assert.strictEqual(diffInput.original, input);
assert.strictEqual(diffInput.modified, otherInput);
assert(diffInput.matches(diffInput));
assert(!diffInput.matches(otherInput));
assert(!diffInput.matches(null));
diffInput.dispose();
assert.strictEqual(counter, 0);

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, EditorInputCapabilities, isEditorIdentifier } from 'vs/workbench/common/editor';
import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, EditorInputCapabilities, isEditorIdentifier, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, isResourceEditorInput, isUntitledResourceEditorInput, isResourceDiffEditorInput, isEditorInputWithOptionsAndGroup, IEditorInputWithOptions, isEditorInputWithOptions, isEditorInput, IEditorInputWithOptionsAndGroup } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { URI } from 'vs/base/common/uri';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -19,6 +19,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
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';
import { EditorResolution, IResourceEditorInput } from 'vs/platform/editor/common/editor';
suite('Workbench editor utils', () => {
@@ -65,6 +66,23 @@ suite('Workbench editor utils', () => {
disposables.clear();
});
test('untyped check functions', () => {
assert.ok(!isResourceEditorInput(undefined));
assert.ok(!isResourceEditorInput({}));
assert.ok(!isResourceEditorInput({ original: { resource: URI.file('/') }, modified: { resource: URI.file('/') } }));
assert.ok(isResourceEditorInput({ resource: URI.file('/') }));
assert.ok(!isUntitledResourceEditorInput(undefined));
assert.ok(isUntitledResourceEditorInput({}));
assert.ok(isUntitledResourceEditorInput({ resource: URI.file('/').with({ scheme: Schemas.untitled }) }));
assert.ok(isUntitledResourceEditorInput({ resource: URI.file('/'), forceUntitled: true }));
assert.ok(!isResourceDiffEditorInput(undefined));
assert.ok(!isResourceDiffEditorInput({}));
assert.ok(!isResourceDiffEditorInput({ resource: URI.file('/') }));
assert.ok(isResourceDiffEditorInput({ original: { resource: URI.file('/') }, modified: { resource: URI.file('/') } }));
});
test('EditorInputCapabilities', () => {
const testInput1 = new TestFileEditorInput(URI.file('resource1'), 'testTypeId');
const testInput2 = new TestFileEditorInput(URI.file('resource2'), 'testTypeId');
@@ -118,7 +136,7 @@ suite('Workbench editor utils', () => {
assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Singleton), true);
});
test('EditorResourceAccessor', () => {
test('EditorResourceAccessor - typed inputs', () => {
const service = accessor.untitledTextEditorService;
assert.ok(!EditorResourceAccessor.getCanonicalUri(null!));
@@ -209,6 +227,101 @@ suite('Workbench editor utils', () => {
assert.strictEqual(EditorResourceAccessor.getOriginalUri(fileWithPreferredResource)?.toString(), preferredResource.toString());
});
test('EditorResourceAccessor - untyped inputs', () => {
assert.ok(!EditorResourceAccessor.getCanonicalUri(null!));
assert.ok(!EditorResourceAccessor.getOriginalUri(null!));
const untitledURI = URI.from({
scheme: Schemas.untitled,
authority: 'foo',
path: '/bar'
});
const untitled: IUntitledTextResourceEditorInput = {
resource: untitledURI
};
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(untitled)!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(untitled, { supportSideBySide: SideBySideEditor.PRIMARY })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(untitled, { supportSideBySide: SideBySideEditor.SECONDARY })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(untitled, { supportSideBySide: SideBySideEditor.BOTH })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(untitled, { filterByScheme: Schemas.untitled })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(untitled, { filterByScheme: [Schemas.file, Schemas.untitled] })!.toString(), untitled.resource?.toString());
assert.ok(!EditorResourceAccessor.getCanonicalUri(untitled, { filterByScheme: Schemas.file }));
assert.strictEqual(EditorResourceAccessor.getOriginalUri(untitled)!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(untitled, { supportSideBySide: SideBySideEditor.PRIMARY })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(untitled, { supportSideBySide: SideBySideEditor.SECONDARY })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(untitled, { supportSideBySide: SideBySideEditor.BOTH })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(untitled, { filterByScheme: Schemas.untitled })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(untitled, { filterByScheme: [Schemas.file, Schemas.untitled] })!.toString(), untitled.resource?.toString());
assert.ok(!EditorResourceAccessor.getOriginalUri(untitled, { filterByScheme: Schemas.file }));
const file: IResourceEditorInput = {
resource: URI.file('/some/path.txt')
};
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(file)!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(file, { supportSideBySide: SideBySideEditor.PRIMARY })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(file, { supportSideBySide: SideBySideEditor.SECONDARY })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(file, { supportSideBySide: SideBySideEditor.BOTH })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(file, { filterByScheme: Schemas.file })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(file, { filterByScheme: [Schemas.file, Schemas.untitled] })!.toString(), file.resource.toString());
assert.ok(!EditorResourceAccessor.getCanonicalUri(file, { filterByScheme: Schemas.untitled }));
assert.strictEqual(EditorResourceAccessor.getOriginalUri(file)!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(file, { supportSideBySide: SideBySideEditor.PRIMARY })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(file, { supportSideBySide: SideBySideEditor.SECONDARY })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(file, { supportSideBySide: SideBySideEditor.BOTH })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(file, { filterByScheme: Schemas.file })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(file, { filterByScheme: [Schemas.file, Schemas.untitled] })!.toString(), file.resource.toString());
assert.ok(!EditorResourceAccessor.getOriginalUri(file, { filterByScheme: Schemas.untitled }));
const diffEditorInput: IResourceDiffEditorInput = {
original: untitled,
modified: file
};
assert.ok(!EditorResourceAccessor.getCanonicalUri(diffEditorInput));
assert.ok(!EditorResourceAccessor.getCanonicalUri(diffEditorInput, { filterByScheme: Schemas.file }));
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.PRIMARY })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.PRIMARY, filterByScheme: Schemas.file })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.PRIMARY, filterByScheme: [Schemas.file, Schemas.untitled] })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.SECONDARY })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.SECONDARY, filterByScheme: Schemas.untitled })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.SECONDARY, filterByScheme: [Schemas.file, Schemas.untitled] })!.toString(), untitled.resource?.toString());
assert.strictEqual((EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH }) as { primary: URI, secondary: URI }).primary.toString(), file.resource.toString());
assert.strictEqual((EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: Schemas.file }) as { primary: URI, secondary: URI }).primary.toString(), file.resource.toString());
assert.strictEqual((EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: [Schemas.file, Schemas.untitled] }) as { primary: URI, secondary: URI }).primary.toString(), file.resource.toString());
assert.strictEqual((EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource?.toString());
assert.strictEqual((EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: Schemas.untitled }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource?.toString());
assert.strictEqual((EditorResourceAccessor.getCanonicalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: [Schemas.file, Schemas.untitled] }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource?.toString());
assert.ok(!EditorResourceAccessor.getOriginalUri(diffEditorInput));
assert.ok(!EditorResourceAccessor.getOriginalUri(diffEditorInput, { filterByScheme: Schemas.file }));
assert.strictEqual(EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.PRIMARY })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.PRIMARY, filterByScheme: Schemas.file })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.PRIMARY, filterByScheme: [Schemas.file, Schemas.untitled] })!.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.SECONDARY })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.SECONDARY, filterByScheme: Schemas.untitled })!.toString(), untitled.resource?.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.SECONDARY, filterByScheme: [Schemas.file, Schemas.untitled] })!.toString(), untitled.resource?.toString());
assert.strictEqual((EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH }) as { primary: URI, secondary: URI }).primary.toString(), file.resource.toString());
assert.strictEqual((EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: Schemas.file }) as { primary: URI, secondary: URI }).primary.toString(), file.resource.toString());
assert.strictEqual((EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: [Schemas.file, Schemas.untitled] }) as { primary: URI, secondary: URI }).primary.toString(), file.resource.toString());
assert.strictEqual((EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource?.toString());
assert.strictEqual((EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: Schemas.untitled }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource?.toString());
assert.strictEqual((EditorResourceAccessor.getOriginalUri(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: [Schemas.file, Schemas.untitled] }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource?.toString());
});
test('isEditorIdentifier', () => {
assert.strictEqual(isEditorIdentifier(undefined), false);
assert.strictEqual(isEditorIdentifier('undefined'), false);
@@ -218,6 +331,24 @@ suite('Workbench editor utils', () => {
assert.strictEqual(isEditorIdentifier({ editor: testInput1, groupId: 3 }), true);
});
test('isEditorInputWithOptionsAndGroup', () => {
const editorInput = new TestFileEditorInput(URI.file('resource1'), 'testTypeId');
assert.strictEqual(isEditorInput(editorInput), true);
assert.strictEqual(isEditorInputWithOptions(editorInput), false);
assert.strictEqual(isEditorInputWithOptionsAndGroup(editorInput), false);
const editorInputWithOptions: IEditorInputWithOptions = { editor: editorInput, options: { override: EditorResolution.PICK } };
assert.strictEqual(isEditorInput(editorInputWithOptions), false);
assert.strictEqual(isEditorInputWithOptions(editorInputWithOptions), true);
assert.strictEqual(isEditorInputWithOptionsAndGroup(editorInputWithOptions), false);
const service = accessor.editorGroupService;
const editorInputWithOptionsAndGroup: IEditorInputWithOptionsAndGroup = { editor: editorInput, options: { override: EditorResolution.PICK }, group: service.activeGroup };
assert.strictEqual(isEditorInput(editorInputWithOptionsAndGroup), false);
assert.strictEqual(isEditorInputWithOptions(editorInputWithOptionsAndGroup), true);
assert.strictEqual(isEditorInputWithOptionsAndGroup(editorInputWithOptionsAndGroup), true);
});
test('whenEditorClosed (single editor)', async function () {
return testWhenEditorClosed(false, false, toResource.call(this, '/path/index.txt'));
});
@@ -247,9 +378,9 @@ suite('Workbench editor utils', () => {
for (const resource of resources) {
if (custom) {
await accessor.editorService.openEditor(new TestFileEditorInput(resource, 'testTypeId'), { pinned: true });
await accessor.editorService.openEditor(new TestFileEditorInput(resource, 'testTypeId'), { pinned: true, override: EditorResolution.DISABLED });
} else if (sideBySide) {
await accessor.editorService.openEditor(new SideBySideEditorInput('testSideBySideEditor', undefined, new TestFileEditorInput(resource, 'testTypeId'), new TestFileEditorInput(resource, 'testTypeId')), { pinned: true });
await accessor.editorService.openEditor(new SideBySideEditorInput('testSideBySideEditor', undefined, new TestFileEditorInput(resource, 'testTypeId'), new TestFileEditorInput(resource, 'testTypeId')), { pinned: true, override: EditorResolution.DISABLED });
} else {
await accessor.editorService.openEditor({ resource, options: { pinned: true } });
}

View File

@@ -5,7 +5,7 @@
import * as assert from 'assert';
import { EditorGroupModel, ISerializedEditorGroupModel, EditorCloseEvent } from 'vs/workbench/common/editor/editorGroupModel';
import { EditorExtensions, IEditorInputFactoryRegistry, IFileEditorInput, IEditorInputSerializer, CloseDirection, EditorsOrder } from 'vs/workbench/common/editor';
import { EditorExtensions, IEditorFactoryRegistry, IFileEditorInput, IEditorSerializer, CloseDirection, EditorsOrder, IResourceDiffEditorInput } 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';
@@ -77,6 +77,7 @@ suite('EditorGroupModel', () => {
}
interface GroupEvents {
locked: number[],
opened: EditorInput[];
activated: EditorInput[];
closed: EditorCloseEvent[];
@@ -90,6 +91,7 @@ suite('EditorGroupModel', () => {
function groupListener(group: EditorGroupModel): GroupEvents {
const groupEvents: GroupEvents = {
locked: [],
opened: [],
closed: [],
activated: [],
@@ -101,6 +103,7 @@ suite('EditorGroupModel', () => {
disposed: []
};
group.onDidChangeLocked(() => groupEvents.locked.push(group.id));
group.onDidOpenEditor(e => groupEvents.opened.push(e));
group.onDidCloseEditor(e => groupEvents.closed.push(e));
group.onDidActivateEditor(e => groupEvents.activated.push(e));
@@ -159,6 +162,7 @@ suite('EditorGroupModel', () => {
super();
}
override get typeId() { return 'testFileEditorInputForGroups'; }
override get editorId() { return this.id; }
override async resolve(): Promise<IEditorModel | null> { return null; }
setPreferredName(name: string): void { }
setPreferredDescription(description: string): void { }
@@ -173,6 +177,9 @@ suite('EditorGroupModel', () => {
isResolved(): boolean { return false; }
override matches(other: TestFileEditorInput): boolean {
if (super.matches(other)) {
return true;
}
return other && this.id === other.id && other instanceof TestFileEditorInput;
}
}
@@ -189,7 +196,7 @@ suite('EditorGroupModel', () => {
id: string;
}
class TestEditorInputSerializer implements IEditorInputSerializer {
class TestEditorInputSerializer implements IEditorSerializer {
static disableSerialize = false;
static disableDeserialize = false;
@@ -228,7 +235,7 @@ suite('EditorGroupModel', () => {
TestEditorInputSerializer.disableSerialize = false;
TestEditorInputSerializer.disableDeserialize = false;
disposables.add(Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).registerEditorInputSerializer('testEditorInputForGroups', TestEditorInputSerializer));
disposables.add(Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer('testEditorInputForGroups', TestEditorInputSerializer));
});
teardown(() => {
@@ -253,9 +260,15 @@ suite('EditorGroupModel', () => {
group.stick(input2);
assert.ok(group.isSticky(input2));
// Locked
assert.strictEqual(group.isLocked, false);
group.lock(true);
assert.strictEqual(group.isLocked, true);
const clone = group.clone();
assert.notStrictEqual(group.id, clone.id);
assert.strictEqual(clone.count, 3);
assert.strictEqual(clone.isLocked, false); // locking does not clone over
let didEditorLabelChange = false;
const toDispose = clone.onDidChangeEditorLabel(() => didEditorLabelChange = true);
@@ -277,7 +290,112 @@ suite('EditorGroupModel', () => {
toDispose.dispose();
});
test('contains()', function () {
test('isActive - untyped', () => {
const group = createEditorGroupModel();
const input = new TestFileEditorInput('testInput', URI.file('fake'));
const input2 = new TestFileEditorInput('testInput2', URI.file('fake2'));
const untypedInput = { resource: URI.file('/fake'), options: { override: 'testInput' } };
const untypedNonActiveInput = { resource: URI.file('/fake2'), options: { override: 'testInput2' } };
group.openEditor(input, { pinned: true, active: true });
group.openEditor(input2, { active: false });
assert.ok(group.isActive(input));
assert.ok(group.isActive(untypedInput));
assert.ok(!group.isActive(untypedNonActiveInput));
});
test('contains() - untyped', function () {
const group = createEditorGroupModel();
const instantiationService = workbenchInstantiationService();
const input1 = input('input1', false, URI.file('/input1'));
const input2 = input('input2', false, URI.file('/input2'));
const untypedInput1 = { resource: URI.file('/input1'), options: { override: 'input1' } };
const untypedInput2 = { resource: URI.file('/input2'), options: { override: 'input2' } };
const diffInput1 = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input1, input2, undefined);
const diffInput2 = instantiationService.createInstance(DiffEditorInput, 'name', 'description', input2, input1, undefined);
const untypedDiffInput1: IResourceDiffEditorInput = {
original: untypedInput1,
modified: untypedInput2
};
const untypedDiffInput2: IResourceDiffEditorInput = {
original: untypedInput2,
modified: untypedInput1
};
group.openEditor(input1, { pinned: true, active: true });
assert.strictEqual(group.contains(untypedInput1), true);
assert.strictEqual(group.contains(untypedInput1, { strictEquals: true }), false);
assert.strictEqual(group.contains(untypedInput1, { supportSideBySide: true }), true);
assert.strictEqual(group.contains(untypedInput2), false);
assert.strictEqual(group.contains(untypedInput2, { strictEquals: true }), false);
assert.strictEqual(group.contains(untypedInput2, { supportSideBySide: true }), false);
assert.strictEqual(group.contains(untypedDiffInput1), false);
assert.strictEqual(group.contains(untypedDiffInput2), false);
group.openEditor(input2, { pinned: true, active: true });
assert.strictEqual(group.contains(untypedInput1), true);
assert.strictEqual(group.contains(untypedInput2), true);
assert.strictEqual(group.contains(untypedDiffInput1), false);
assert.strictEqual(group.contains(untypedDiffInput2), false);
group.openEditor(diffInput1, { pinned: true, active: true });
assert.strictEqual(group.contains(untypedInput1), true);
assert.strictEqual(group.contains(untypedInput2), true);
assert.strictEqual(group.contains(untypedDiffInput1), true);
assert.strictEqual(group.contains(untypedDiffInput2), false);
group.openEditor(diffInput2, { pinned: true, active: true });
assert.strictEqual(group.contains(untypedInput1), true);
assert.strictEqual(group.contains(untypedInput2), true);
assert.strictEqual(group.contains(untypedDiffInput1), true);
assert.strictEqual(group.contains(untypedDiffInput2), true);
group.closeEditor(input1);
assert.strictEqual(group.contains(untypedInput1), false);
assert.strictEqual(group.contains(untypedInput1, { supportSideBySide: true }), true);
assert.strictEqual(group.contains(untypedInput2), true);
assert.strictEqual(group.contains(untypedDiffInput1), true);
assert.strictEqual(group.contains(untypedDiffInput2), true);
group.closeEditor(input2);
assert.strictEqual(group.contains(untypedInput1), false);
assert.strictEqual(group.contains(untypedInput1, { supportSideBySide: true }), true);
assert.strictEqual(group.contains(untypedInput2), false);
assert.strictEqual(group.contains(untypedInput2, { supportSideBySide: true }), true);
assert.strictEqual(group.contains(untypedDiffInput1), true);
assert.strictEqual(group.contains(untypedDiffInput2), true);
group.closeEditor(diffInput1);
assert.strictEqual(group.contains(untypedInput1), false);
assert.strictEqual(group.contains(untypedInput1, { supportSideBySide: true }), true);
assert.strictEqual(group.contains(untypedInput2), false);
assert.strictEqual(group.contains(untypedInput2, { supportSideBySide: true }), true);
assert.strictEqual(group.contains(untypedDiffInput1), false);
assert.strictEqual(group.contains(untypedDiffInput2), true);
group.closeEditor(diffInput2);
assert.strictEqual(group.contains(untypedInput1), false);
assert.strictEqual(group.contains(untypedInput1, { supportSideBySide: true }), false);
assert.strictEqual(group.contains(untypedInput2), false);
assert.strictEqual(group.contains(untypedInput2, { supportSideBySide: true }), false);
assert.strictEqual(group.contains(untypedDiffInput1), false);
assert.strictEqual(group.contains(untypedDiffInput2), false);
});
test('contains()', () => {
const group = createEditorGroupModel();
const instantiationService = workbenchInstantiationService();
@@ -368,7 +486,7 @@ suite('EditorGroupModel', () => {
});
test('group serialization', function () {
inst().invokeFunction(accessor => Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor));
inst().invokeFunction(accessor => Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).start(accessor));
const group = createEditorGroupModel();
const input1 = input();
@@ -412,7 +530,7 @@ suite('EditorGroupModel', () => {
});
test('group serialization (sticky editor)', function () {
inst().invokeFunction(accessor => Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor));
inst().invokeFunction(accessor => Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).start(accessor));
const group = createEditorGroupModel();
const input1 = input();
@@ -466,6 +584,40 @@ suite('EditorGroupModel', () => {
assert.strictEqual(deserialized.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0);
});
test('group serialization (locked group)', function () {
const group = createEditorGroupModel();
const events = groupListener(group);
assert.strictEqual(events.locked.length, 0);
group.lock(true);
group.lock(true);
assert.strictEqual(events.locked.length, 1);
group.lock(false);
group.lock(false);
assert.strictEqual(events.locked.length, 2);
});
test('locked group', function () {
const group = createEditorGroupModel();
group.lock(true);
let deserialized = createEditorGroupModel(group.serialize());
assert.strictEqual(group.id, deserialized.id);
assert.strictEqual(deserialized.count, 0);
assert.strictEqual(deserialized.isLocked, true);
group.lock(false);
deserialized = createEditorGroupModel(group.serialize());
assert.strictEqual(group.id, deserialized.id);
assert.strictEqual(deserialized.count, 0);
assert.strictEqual(deserialized.isLocked, false);
});
test('One Editor', function () {
const group = createEditorGroupModel();
const events = groupListener(group);
@@ -1287,7 +1439,7 @@ suite('EditorGroupModel', () => {
config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } });
inst.stub(IConfigurationService, config);
inst.invokeFunction(accessor => Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor));
inst.invokeFunction(accessor => Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).start(accessor));
let group = createEditorGroupModel();
@@ -1321,7 +1473,7 @@ suite('EditorGroupModel', () => {
config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } });
inst.stub(IConfigurationService, config);
inst.invokeFunction(accessor => Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor));
inst.invokeFunction(accessor => Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).start(accessor));
let group1 = createEditorGroupModel();
@@ -1391,7 +1543,7 @@ suite('EditorGroupModel', () => {
config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } });
inst.stub(IConfigurationService, config);
inst.invokeFunction(accessor => Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor));
inst.invokeFunction(accessor => Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).start(accessor));
let group = createEditorGroupModel();
@@ -1435,7 +1587,7 @@ suite('EditorGroupModel', () => {
config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } });
inst.stub(IConfigurationService, config);
inst.invokeFunction(accessor => Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor));
inst.invokeFunction(accessor => Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).start(accessor));
let group = createEditorGroupModel();
@@ -1470,7 +1622,7 @@ suite('EditorGroupModel', () => {
config.setUserConfiguration('workbench', { editor: { openPositioning: 'right' } });
inst.stub(IConfigurationService, config);
inst.invokeFunction(accessor => Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).start(accessor));
inst.invokeFunction(accessor => Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).start(accessor));
let group1 = createEditorGroupModel();
let group2 = createEditorGroupModel();

View File

@@ -4,7 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { isEditorInput, isResourceDiffEditorInput, isResourceEditorInput, isUntitledResourceEditorInput } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { TestEditorInput } from 'vs/workbench/test/browser/workbenchTestServices';
suite('EditorInput', () => {
@@ -20,9 +23,17 @@ suite('EditorInput', () => {
let input = new MyEditorInput();
let otherInput = new MyEditorInput();
assert.ok(isEditorInput(input));
assert.ok(!isEditorInput(undefined));
assert.ok(!isEditorInput({ resource: URI.file('/') }));
assert.ok(!isEditorInput({}));
assert.ok(!isResourceEditorInput(input));
assert.ok(!isUntitledResourceEditorInput(input));
assert.ok(!isResourceDiffEditorInput(input));
assert(input.matches(input));
assert(!input.matches(otherInput));
assert(!input.matches(null));
assert(input.getName());
input.onWillDispose(() => {
@@ -33,4 +44,20 @@ suite('EditorInput', () => {
input.dispose();
assert.strictEqual(counter, 1);
});
test('untyped matches', () => {
const testInputID = 'untypedMatches';
const testInputResource = URI.file('/fake');
const testInput = new TestEditorInput(testInputResource, testInputID);
const testUntypedInput = { resource: testInputResource, options: { override: testInputID } };
const tetUntypedInputWrongResource = { resource: URI.file('/incorrectFake'), options: { override: testInputID } };
const testUntypedInputWrongId = { resource: testInputResource, options: { override: 'wrongId' } };
const testUntypedInputWrong = { resource: URI.file('/incorrectFake'), options: { override: 'wrongId' } };
assert(testInput.matches(testUntypedInput));
assert.ok(!testInput.matches(tetUntypedInputWrongResource));
assert.ok(!testInput.matches(testUntypedInputWrongId));
assert.ok(!testInput.matches(testUntypedInputWrong));
});
});

View File

@@ -26,6 +26,10 @@ import { TestTextResourcePropertiesService } from 'vs/workbench/test/common/work
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';
import { Mimes } from 'vs/base/common/mime';
import { LanguageDetectionService } from 'vs/workbench/services/languageDetection/browser/languageDetectionWorkerServiceImpl';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { TestEnvironmentService } from 'vs/workbench/test/browser/workbenchTestServices';
suite('EditorModel', () => {
@@ -44,6 +48,7 @@ suite('EditorModel', () => {
const dialogService = new TestDialogService();
const notificationService = new TestNotificationService();
const undoRedoService = new UndoRedoService(dialogService, notificationService);
instantiationService.stub(IWorkbenchEnvironmentService, TestEnvironmentService);
instantiationService.stub(IConfigurationService, new TestConfigurationService());
instantiationService.stub(ITextResourcePropertiesService, new TestTextResourcePropertiesService(instantiationService.get(IConfigurationService)));
instantiationService.stub(IDialogService, dialogService);
@@ -83,10 +88,10 @@ suite('EditorModel', () => {
test('BaseTextEditorModel', async () => {
let modelService = stubModelService(instantiationService);
const model = new MyTextEditorModel(modelService, modeService);
const model = new MyTextEditorModel(modelService, modeService, instantiationService.createInstance(LanguageDetectionService));
await model.resolve();
model.createTextEditorModel(createTextBufferFactory('foo'), null!, 'text/plain');
model.createTextEditorModel(createTextBufferFactory('foo'), null!, Mimes.text);
assert.strictEqual(model.isResolved(), true);
model.dispose();
});

View File

@@ -5,18 +5,18 @@
import * as assert from 'assert';
import { EditorPane, EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane';
import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor';
import { IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor';
import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/editorPlaceholder';
import { IEditorSerializer, IEditorFactoryRegistry, 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, createEditorPart } from 'vs/workbench/test/browser/workbenchTestServices';
import { workbenchInstantiationService, TestEditorGroupView, TestEditorGroupsService, registerTestResourceEditor, TestEditorInput, createEditorPart, TestTextResourceConfigurationService } 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 { EditorDescriptor, EditorRegistry } from 'vs/workbench/browser/editor';
import { EditorPaneDescriptor, EditorPaneRegistry } 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';
@@ -28,11 +28,12 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
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';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
const NullThemeService = new TestThemeService();
const editorRegistry: EditorRegistry = Registry.as(EditorExtensions.Editors);
const editorInputRegistry: IEditorInputFactoryRegistry = Registry.as(EditorExtensions.EditorInputFactories);
const editorRegistry: EditorPaneRegistry = Registry.as(EditorExtensions.EditorPane);
const editorInputRegistry: IEditorFactoryRegistry = Registry.as(EditorExtensions.EditorFactory);
class TestEditor extends EditorPane {
@@ -57,7 +58,7 @@ export class OtherTestEditor extends EditorPane {
createEditor(): any { }
}
class TestInputSerializer implements IEditorInputSerializer {
class TestInputSerializer implements IEditorSerializer {
canSerialize(editorInput: EditorInput): boolean {
return true;
@@ -76,7 +77,7 @@ class TestInput extends EditorInput {
readonly resource = undefined;
override prefersEditor<T extends IEditorDescriptor<IEditorPane>>(editors: T[]): T | undefined {
override prefersEditorPane<T extends IEditorDescriptor<IEditorPane>>(editors: T[]): T | undefined {
return editors[1];
}
@@ -130,61 +131,61 @@ suite('EditorPane', () => {
assert(!editor.getControl());
});
test('EditorDescriptor', () => {
const editorDescriptor = EditorDescriptor.create(TestEditor, 'id', 'name');
test('EditorPaneDescriptor', () => {
const editorDescriptor = EditorPaneDescriptor.create(TestEditor, 'id', 'name');
assert.strictEqual(editorDescriptor.typeId, 'id');
assert.strictEqual(editorDescriptor.name, 'name');
});
test('Editor Registration', function () {
const editorDescriptor1 = EditorDescriptor.create(TestEditor, 'id1', 'name');
const editorDescriptor2 = EditorDescriptor.create(OtherTestEditor, 'id2', 'name');
test('Editor Pane Registration', function () {
const editorDescriptor1 = EditorPaneDescriptor.create(TestEditor, 'id1', 'name');
const editorDescriptor2 = EditorPaneDescriptor.create(OtherTestEditor, 'id2', 'name');
const oldEditorsCnt = editorRegistry.getEditors().length;
const oldInputCnt = editorRegistry.getEditorInputs().length;
const oldEditorsCnt = editorRegistry.getEditorPanes().length;
const oldInputCnt = editorRegistry.getEditors().length;
const dispose1 = editorRegistry.registerEditor(editorDescriptor1, [new SyncDescriptor(TestInput)]);
const dispose2 = editorRegistry.registerEditor(editorDescriptor2, [new SyncDescriptor(TestInput), new SyncDescriptor(OtherTestInput)]);
const dispose1 = editorRegistry.registerEditorPane(editorDescriptor1, [new SyncDescriptor(TestInput)]);
const dispose2 = editorRegistry.registerEditorPane(editorDescriptor2, [new SyncDescriptor(TestInput), new SyncDescriptor(OtherTestInput)]);
assert.strictEqual(editorRegistry.getEditors().length, oldEditorsCnt + 2);
assert.strictEqual(editorRegistry.getEditorInputs().length, oldInputCnt + 3);
assert.strictEqual(editorRegistry.getEditorPanes().length, oldEditorsCnt + 2);
assert.strictEqual(editorRegistry.getEditors().length, oldInputCnt + 3);
assert.strictEqual(editorRegistry.getEditor(new TestInput()), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditor(new OtherTestInput()), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditorPane(new TestInput()), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditorPane(new OtherTestInput()), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditorByType('id1'), editorDescriptor1);
assert.strictEqual(editorRegistry.getEditorByType('id2'), editorDescriptor2);
assert(!editorRegistry.getEditorByType('id3'));
assert.strictEqual(editorRegistry.getEditorPaneByType('id1'), editorDescriptor1);
assert.strictEqual(editorRegistry.getEditorPaneByType('id2'), editorDescriptor2);
assert(!editorRegistry.getEditorPaneByType('id3'));
dispose([dispose1, dispose2]);
});
test('Editor Lookup favors specific class over superclass (match on specific class)', function () {
const d1 = EditorDescriptor.create(TestEditor, 'id1', 'name');
test('Editor Pane Lookup favors specific class over superclass (match on specific class)', function () {
const d1 = EditorPaneDescriptor.create(TestEditor, 'id1', 'name');
const disposables = new DisposableStore();
disposables.add(registerTestResourceEditor());
disposables.add(editorRegistry.registerEditor(d1, [new SyncDescriptor(TestResourceEditorInput)]));
disposables.add(editorRegistry.registerEditorPane(d1, [new SyncDescriptor(TestResourceEditorInput)]));
const inst = workbenchInstantiationService();
const editor = editorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined))!.instantiate(inst);
const editor = editorRegistry.getEditorPane(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined))!.instantiate(inst);
assert.strictEqual(editor.getId(), 'testEditor');
const otherEditor = editorRegistry.getEditor(inst.createInstance(TextResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined))!.instantiate(inst);
const otherEditor = editorRegistry.getEditorPane(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 () {
test('Editor Pane Lookup favors specific class over superclass (match on super class)', function () {
const inst = workbenchInstantiationService();
const disposables = new DisposableStore();
disposables.add(registerTestResourceEditor());
const editor = editorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined))!.instantiate(inst);
const editor = editorRegistry.getEditorPane(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined))!.instantiate(inst);
assert.strictEqual('workbench.editors.textResourceEditor', editor.getId());
@@ -194,16 +195,16 @@ suite('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);
const disposable = editorInputRegistry.registerEditorSerializer(testInput.typeId, TestInputSerializer);
let factory = editorInputRegistry.getEditorInputSerializer('testTypeId');
let factory = editorInputRegistry.getEditorSerializer('testTypeId');
assert(factory);
factory = editorInputRegistry.getEditorInputSerializer(testInput);
factory = editorInputRegistry.getEditorSerializer(testInput);
assert(factory);
// throws when registering serializer for same type
assert.throws(() => editorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer));
assert.throws(() => editorInputRegistry.registerEditorSerializer(testInput.typeId, TestInputSerializer));
disposable.dispose();
});
@@ -213,6 +214,8 @@ suite('EditorPane', () => {
const testGroup1 = new TestEditorGroupView(1);
const testGroup4 = new TestEditorGroupView(4);
const configurationService = new TestTextResourceConfigurationService();
const editorGroupService = new TestEditorGroupsService([
testGroup0,
testGroup1,
@@ -224,7 +227,7 @@ suite('EditorPane', () => {
}
const rawMemento = Object.create(null);
let memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService);
let memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService);
let res = memento.loadEditorState(testGroup0, URI.file('/A'));
assert.ok(!res);
@@ -259,7 +262,7 @@ suite('EditorPane', () => {
memento.saveState();
memento = new EditorMemento('id', 'key', rawMemento, 3, editorGroupService);
memento = new EditorMemento('id', 'key', rawMemento, 3, editorGroupService, configurationService);
assert.ok(memento.loadEditorState(testGroup0, URI.file('/C')));
assert.ok(memento.loadEditorState(testGroup0, URI.file('/D')));
assert.ok(memento.loadEditorState(testGroup0, URI.file('/E')));
@@ -279,12 +282,13 @@ suite('EditorPane', () => {
test('EditorMemento - move', function () {
const testGroup0 = new TestEditorGroupView(0);
const configurationService = new TestTextResourceConfigurationService();
const editorGroupService = new TestEditorGroupsService([testGroup0]);
interface TestViewState { line: number; }
const rawMemento = Object.create(null);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService);
memento.saveEditorState(testGroup0, URI.file('/some/folder/file-1.txt'), { line: 1 });
memento.saveEditorState(testGroup0, URI.file('/some/folder/file-2.txt'), { line: 2 });
@@ -327,7 +331,7 @@ suite('EditorPane', () => {
}
const rawMemento = Object.create(null);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService());
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService(), new TestTextResourceConfigurationService());
const testInputA = new TestEditorInput(URI.file('/A'));
@@ -365,7 +369,7 @@ suite('EditorPane', () => {
}
const rawMemento = Object.create(null);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService());
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService(), new TestTextResourceConfigurationService());
const testInputA = new TestEditorInput(URI.file('/A'));
@@ -401,6 +405,55 @@ suite('EditorPane', () => {
assert.ok(!res);
});
test('EditorMemento - workbench.editor.sharedViewState', function () {
const testGroup0 = new TestEditorGroupView(0);
const testGroup1 = new TestEditorGroupView(1);
const configurationService = new TestTextResourceConfigurationService(new TestConfigurationService({
workbench: {
editor: {
sharedViewState: true
}
}
}));
const editorGroupService = new TestEditorGroupsService([testGroup0]);
interface TestViewState { line: number; }
const rawMemento = Object.create(null);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService);
const resource = URI.file('/some/folder/file-1.txt');
memento.saveEditorState(testGroup0, resource, { line: 1 });
let res = memento.loadEditorState(testGroup0, resource);
assert.strictEqual(res!.line, 1);
res = memento.loadEditorState(testGroup1, resource);
assert.strictEqual(res!.line, 1);
memento.saveEditorState(testGroup0, resource, { line: 3 });
res = memento.loadEditorState(testGroup1, resource);
assert.strictEqual(res!.line, 3);
memento.saveEditorState(testGroup1, resource, { line: 1 });
res = memento.loadEditorState(testGroup1, resource);
assert.strictEqual(res!.line, 1);
memento.clearEditorState(resource, testGroup0);
memento.clearEditorState(resource, testGroup1);
res = memento.loadEditorState(testGroup1, resource);
assert.strictEqual(res!.line, 1);
memento.clearEditorState(resource);
res = memento.loadEditorState(testGroup1, resource);
assert.ok(!res);
});
test('WorkspaceTrustRequiredEditor', async function () {
class TrustRequiredTestEditor extends EditorPane {
@@ -445,8 +498,8 @@ suite('EditorPane', () => {
const group = editorPart.activeGroup;
const editorDescriptor = EditorDescriptor.create(TrustRequiredTestEditor, 'id1', 'name');
disposables.add(editorRegistry.registerEditor(editorDescriptor, [new SyncDescriptor(TrustRequiredTestInput)]));
const editorDescriptor = EditorPaneDescriptor.create(TrustRequiredTestEditor, 'id1', 'name');
disposables.add(editorRegistry.registerEditorPane(editorDescriptor, [new SyncDescriptor(TrustRequiredTestInput)]));
const testInput = new TrustRequiredTestInput();

View File

@@ -4,8 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { IResourceDiffEditorInput, isSideBySideEditorInput } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
import { TestFileEditorInput } from 'vs/workbench/test/browser/workbenchTestServices';
suite('SideBySideEditorInput', () => {
@@ -34,6 +37,8 @@ suite('SideBySideEditorInput', () => {
const sideBySideInut = new SideBySideEditorInput('name', 'description', otherInput, input);
assert.ok(isSideBySideEditorInput(sideBySideInut));
let capabilitiesChangeCounter = 0;
sideBySideInut.onDidChangeCapabilities(() => capabilitiesChangeCounter++);
@@ -58,4 +63,29 @@ suite('SideBySideEditorInput', () => {
assert.strictEqual(labelChangeCounter, 1);
});
// TODO@lramos15 enable when https://github.com/microsoft/vscode/issues/127131 lands
test.skip('untyped matches', () => {
const primaryInput = new TestFileEditorInput(URI.file('/fake'), 'primaryId');
const secondaryInput = new TestFileEditorInput(URI.file('/fake2'), 'secondaryId');
const sideBySideInput = new SideBySideEditorInput('Side By Side Test', undefined, secondaryInput, primaryInput);
const primaryUntypedInput = { resource: URI.file('/fake'), options: { override: 'primaryId' } };
const secondaryUntypedInput = { resource: URI.file('/fake2'), options: { override: 'secondaryId' } };
const sideBySideUntyped: IResourceDiffEditorInput = { original: secondaryUntypedInput, modified: primaryUntypedInput };
assert.ok(sideBySideInput.matches(sideBySideUntyped));
const primaryUntypedInput2 = { resource: URI.file('/fake'), options: { override: 'primaryIdWrong' } };
const secondaryUntypedInput2 = { resource: URI.file('/fake2'), options: { override: 'secondaryId' } };
const sideBySideUntyped2: IResourceDiffEditorInput = { original: secondaryUntypedInput2, modified: primaryUntypedInput2 };
assert.ok(!sideBySideInput.matches(sideBySideUntyped2));
const primaryUntypedInput3 = { resource: URI.file('/fake'), options: { override: 'primaryId' } };
const secondaryUntypedInput3 = { resource: URI.file('/fake2Wrong'), options: { override: 'secondaryId' } };
const sideBySideUntyped3: IResourceDiffEditorInput = { original: secondaryUntypedInput3, modified: primaryUntypedInput3 };
assert.ok(!sideBySideInput.matches(sideBySideUntyped3));
});
});

View File

@@ -5,12 +5,12 @@
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 { basename, isEqual } 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 { 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 { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorsOrder, IFileEditorInput, IEditorFactoryRegistry, IEditorSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, IEditorMoveEvent, EditorExtensions as Extensions, EditorInputCapabilities, IEditorOpenEvent, IUntypedEditorInput } 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 { IResolvedWorkingCopyBackup, IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
@@ -18,12 +18,12 @@ import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configur
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, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor';
import { IEditorOptions, IResourceEditorInput, IEditorModel, IResourceEditorInputIdentifier, ITextResourceEditorInput, ITextEditorOptions } 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, IFileSystemProviderCapabilitiesChangeEvent } 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, IRawFileChangesEvent } 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';
@@ -52,9 +52,9 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IDecorationsService, IResourceDecorationChangeEvent, IDecoration, IDecorationData, IDecorationsProvider } from 'vs/workbench/services/decorations/browser/decorations';
import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IEditorGroupsService, IEditorGroup, GroupsOrder, GroupsArrangement, GroupDirection, IAddGroupOptions, IMergeGroupOptions, IEditorReplacement, IGroupChangeEvent, IFindGroupScope, EditorGroupLayout, ICloseEditorOptions, GroupOrientation, ICloseAllEditorsOptions, ICloseEditorsFilter } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService, ISaveEditorsOptions, IRevertAllEditorsOptions, IResourceEditorInputType, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService';
import { IEditorService, ISaveEditorsOptions, IRevertAllEditorsOptions, PreferredGroup } from 'vs/workbench/services/editor/common/editorService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor';
import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/editor';
import { Dimension, IDimension } from 'vs/base/browser/dom';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { ILabelService } from 'vs/platform/label/common/label';
@@ -126,14 +126,14 @@ import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEd
import { IEnterWorkspaceResult, IRecent, IRecentlyOpened, IWorkspaceFolderCreationData, IWorkspaceIdentifier, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
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 { IShellLaunchConfig, ITerminalChildProcess, ITerminalProfile, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalLocation, 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 { ICreateTerminalOptions, ITerminalInstance, ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { isArray } from 'vs/base/common/types';
import { IShellLaunchConfigResolveOptions, ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal';
import { EditorOverrideService } from 'vs/workbench/services/editor/browser/editorOverrideService';
import { ILocalTerminalService, IShellLaunchConfigResolveOptions, ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal';
import { EditorResolverService } from 'vs/workbench/services/editor/browser/editorResolverService';
import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files';
import { IEditorOverrideService } from 'vs/workbench/services/editor/common/editorOverrideService';
import { IEditorResolverService } from 'vs/workbench/services/editor/common/editorResolverService';
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';
@@ -146,15 +146,15 @@ export function createFileEditorInput(instantiationService: IInstantiationServic
return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined, undefined, undefined, undefined, undefined);
}
Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).registerFileEditorInputFactory({
Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerFileEditorFactory({
typeId: FILE_EDITOR_INPUT_ID,
createFileEditorInput: (resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredMode, preferredContents, instantiationService): IFileEditorInput => {
createFileEditor: (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 => {
isFileEditor: (obj): obj is IFileEditorInput => {
return obj instanceof FileEditorInput;
}
});
@@ -168,6 +168,14 @@ export class TestTextResourceEditor extends TextResourceEditor {
export class TestTextFileEditor extends TextFileEditor {
lastSetOptions: ITextEditorOptions | undefined = undefined;
override setOptions(options: ITextEditorOptions | undefined): void {
this.lastSetOptions = options;
super.setOptions(options);
}
protected override createEditorControl(parent: HTMLElement, configuration: any): IEditor {
return this.instantiationService.createInstance(TestCodeEditor, parent, configuration, {});
}
@@ -197,7 +205,13 @@ export function workbenchInstantiationService(
instantiationService.stub(IProgressService, new TestProgressService());
const workspaceContextService = new TestContextService(TestWorkspace);
instantiationService.stub(IWorkspaceContextService, workspaceContextService);
const configService = new TestConfigurationService();
const configService = new TestConfigurationService({
files: {
participants: {
timeout: 60000
}
}
});
instantiationService.stub(IConfigurationService, configService);
instantiationService.stub(IFilesConfigurationService, disposables.add(new TestFilesConfigurationService(contextKeyService, configService)));
instantiationService.stub(ITextResourceConfigurationService, new TestTextResourceConfigurationService(configService));
@@ -240,7 +254,7 @@ export function workbenchInstantiationService(
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(IEditorResolverService, disposables.add(instantiationService.createInstance(EditorResolverService)));
instantiationService.stub(ICodeEditorService, disposables.add(new CodeEditorService(editorService, themeService, configService)));
instantiationService.stub(IViewletService, new TestViewletService());
instantiationService.stub(IListService, new TestListService());
@@ -270,7 +284,7 @@ export class TestServiceAccessor {
@IWorkbenchEnvironmentService public environmentService: IWorkbenchEnvironmentService,
@IPathService public pathService: IPathService,
@IEditorGroupsService public editorGroupService: IEditorGroupsService,
@IEditorOverrideService public editorOverrideService: IEditorOverrideService,
@IEditorResolverService public editorResolverService: IEditorResolverService,
@IModeService public modeService: IModeService,
@ITextModelService public textModelResolverService: ITextModelService,
@IUntitledTextEditorService public untitledTextEditorService: UntitledTextEditorService,
@@ -650,6 +664,7 @@ export class TestEditorGroupsService implements IEditorGroupsService {
onDidRemoveGroup: Event<IEditorGroup> = Event.None;
onDidMoveGroup: Event<IEditorGroup> = Event.None;
onDidChangeGroupIndex: Event<IEditorGroup> = Event.None;
onDidChangeGroupLocked: Event<IEditorGroup> = Event.None;
onDidLayout: Event<IDimension> = Event.None;
onDidChangeEditorPartOptions = Event.None;
@@ -699,6 +714,7 @@ export class TestEditorGroupView implements IEditorGroupView {
disposed!: boolean;
editors: readonly IEditorInput[] = [];
label!: string;
isLocked!: boolean;
ariaLabel!: string;
index!: number;
whenRestored: Promise<void> = Promise.resolve(undefined);
@@ -731,8 +747,8 @@ export class TestEditorGroupView implements IEditorGroupView {
openEditors(_editors: IEditorInputWithOptions[]): Promise<IEditorPane> { throw new Error('not implemented'); }
isPinned(_editor: IEditorInput): boolean { return false; }
isSticky(_editor: IEditorInput): boolean { return false; }
isActive(_editor: IEditorInput): boolean { return false; }
contains(candidate: IEditorInput): boolean { return false; }
isActive(_editor: IEditorInput | IUntypedEditorInput): boolean { return false; }
contains(candidate: IEditorInput | IUntypedEditorInput): boolean { return false; }
moveEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions): void { }
copyEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions): void { }
async closeEditor(_editor?: IEditorInput, options?: ICloseEditorOptions): Promise<void> { }
@@ -742,6 +758,7 @@ export class TestEditorGroupView implements IEditorGroupView {
pinEditor(_editor?: IEditorInput): void { }
stickEditor(editor?: IEditorInput | undefined): void { }
unstickEditor(editor?: IEditorInput | undefined): void { }
lock(locked: boolean): void { }
focus(): void { }
get scopedContextKeyService(): IContextKeyService { throw new Error('not implemented'); }
setActive(_isActive: boolean): void { }
@@ -805,13 +822,13 @@ export class TestEditorService implements EditorServiceImpl {
constructor(private editorGroupService?: IEditorGroupsService) { }
getEditors() { return []; }
findEditors() { return [] as any; }
openEditor(editor: IEditorInput, options?: IEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditorPane | undefined>;
openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<ITextEditorPane | undefined>;
openEditor(editor: IResourceDiffEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<ITextDiffEditorPane | undefined>;
async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditorPane | undefined> {
openEditor(editor: IEditorInput, options?: IEditorOptions, group?: PreferredGroup): Promise<IEditorPane | undefined>;
openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: PreferredGroup): Promise<ITextEditorPane | undefined>;
openEditor(editor: IResourceDiffEditorInput, group?: PreferredGroup): Promise<ITextDiffEditorPane | undefined>;
async openEditor(editor: IEditorInput | IUntypedEditorInput, optionsOrGroup?: IEditorOptions | PreferredGroup, group?: PreferredGroup): Promise<IEditorPane | undefined> {
throw new Error('not implemented');
}
doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined {
doResolveEditorOpenRequest(editor: IEditorInput | IUntypedEditorInput): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined {
if (!this.editorGroupService) {
return undefined;
}
@@ -820,6 +837,7 @@ export class TestEditorService implements EditorServiceImpl {
}
openEditors(_editors: any, _group?: any): Promise<IEditorPane[]> { throw new Error('not implemented'); }
isOpened(_editor: IResourceEditorInputIdentifier): boolean { return false; }
isVisible(_editor: IEditorInput): boolean { return false; }
replaceEditors(_editors: any, _group: any) { return Promise.resolve(undefined); }
createEditorInput(_input: IResourceEditorInput | IUntitledTextResourceEditorInput | IResourceDiffEditorInput): EditorInput { throw new Error('not implemented'); }
save(editors: IEditorIdentifier[], options?: ISaveEditorsOptions): Promise<boolean> { throw new Error('Method not implemented.'); }
@@ -836,6 +854,9 @@ export class TestFileService implements IFileService {
get onDidFilesChange(): Event<FileChangesEvent> { return this._onDidFilesChange.event; }
fireFileChanges(event: FileChangesEvent): void { this._onDidFilesChange.fire(event); }
private readonly _onDidChangeFilesRaw = new Emitter<IRawFileChangesEvent>();
get onDidChangeFilesRaw(): Event<IRawFileChangesEvent> { return this._onDidChangeFilesRaw.event; }
private readonly _onDidRunOperation = new Emitter<FileOperationEvent>();
get onDidRunOperation(): Event<FileOperationEvent> { return this._onDidRunOperation.event; }
fireAfterOperation(event: FileOperationEvent): void { this._onDidRunOperation.fire(event); }
@@ -1297,13 +1318,28 @@ export class TestEditorInput extends EditorInput {
return this._typeId;
}
override get editorId(): string {
return this._typeId;
}
override resolve(): Promise<IEditorModel | null> {
return Promise.resolve(null);
}
}
export abstract class TestEditorWithOptions extends EditorPane {
lastSetOptions: ITextEditorOptions | undefined = undefined;
override setOptions(options: ITextEditorOptions | undefined): void {
this.lastSetOptions = options;
super.setOptions(options);
}
}
export function registerTestEditor(id: string, inputs: SyncDescriptor<EditorInput>[], serializerInputId?: string): IDisposable {
class TestEditor extends EditorPane {
class TestEditor extends TestEditorWithOptions {
private _scopedContextKeyService: IContextKeyService;
@@ -1329,7 +1365,7 @@ export function registerTestEditor(id: string, inputs: SyncDescriptor<EditorInpu
const disposables = new DisposableStore();
disposables.add(Registry.as<IEditorRegistry>(Extensions.Editors).registerEditor(EditorDescriptor.create(TestEditor, id, 'Test Editor Control'), inputs));
disposables.add(Registry.as<IEditorPaneRegistry>(Extensions.EditorPane).registerEditorPane(EditorPaneDescriptor.create(TestEditor, id, 'Test Editor Control'), inputs));
if (serializerInputId) {
@@ -1337,7 +1373,7 @@ export function registerTestEditor(id: string, inputs: SyncDescriptor<EditorInpu
resource: string;
}
class EditorsObserverTestEditorInputSerializer implements IEditorInputSerializer {
class EditorsObserverTestEditorInputSerializer implements IEditorSerializer {
canSerialize(editorInput: EditorInput): boolean {
return true;
@@ -1359,7 +1395,7 @@ export function registerTestEditor(id: string, inputs: SyncDescriptor<EditorInpu
}
}
disposables.add(Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).registerEditorInputSerializer(serializerInputId, EditorsObserverTestEditorInputSerializer));
disposables.add(Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(serializerInputId, EditorsObserverTestEditorInputSerializer));
}
return disposables;
@@ -1368,8 +1404,8 @@ export function registerTestEditor(id: string, inputs: SyncDescriptor<EditorInpu
export function registerTestFileEditor(): IDisposable {
const disposables = new DisposableStore();
disposables.add(Registry.as<IEditorRegistry>(Extensions.Editors).registerEditor(
EditorDescriptor.create(
disposables.add(Registry.as<IEditorPaneRegistry>(Extensions.EditorPane).registerEditorPane(
EditorPaneDescriptor.create(
TestTextFileEditor,
TestTextFileEditor.ID,
'Text File Editor'
@@ -1383,8 +1419,8 @@ export function registerTestFileEditor(): IDisposable {
export function registerTestResourceEditor(): IDisposable {
const disposables = new DisposableStore();
disposables.add(Registry.as<IEditorRegistry>(Extensions.Editors).registerEditor(
EditorDescriptor.create(
disposables.add(Registry.as<IEditorPaneRegistry>(Extensions.EditorPane).registerEditorPane(
EditorPaneDescriptor.create(
TestTextResourceEditor,
TestTextResourceEditor.ID,
'Text Editor'
@@ -1401,8 +1437,8 @@ export function registerTestResourceEditor(): IDisposable {
export function registerTestSideBySideEditor(): IDisposable {
const disposables = new DisposableStore();
disposables.add(Registry.as<IEditorRegistry>(Extensions.Editors).registerEditor(
EditorDescriptor.create(
disposables.add(Registry.as<IEditorPaneRegistry>(Extensions.EditorPane).registerEditorPane(
EditorPaneDescriptor.create(
SideBySideEditor,
SideBySideEditor.ID,
'Text Editor'
@@ -1426,6 +1462,8 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput
dirty = false;
private fails = false;
disableToUntyped = false;
constructor(
public resource: URI,
private _typeId: string
@@ -1434,6 +1472,7 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput
}
override get typeId() { return this._typeId; }
override get editorId() { return this._typeId; }
private _capabilities: EditorInputCapabilities = EditorInputCapabilities.None;
override get capabilities(): EditorInputCapabilities { return this._capabilities; }
@@ -1445,7 +1484,15 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput
}
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); }
override matches(other: EditorInput | IResourceEditorInput | ITextResourceEditorInput | IUntitledTextResourceEditorInput): boolean {
if (super.matches(other)) {
return true;
}
if (other instanceof EditorInput) {
return !!(other?.resource && this.resource.toString() === other.resource.toString() && other instanceof TestFileEditorInput && other.typeId === this.typeId);
}
return isEqual(this.resource, other.resource) && this.editorId === other.options?.override;
}
setPreferredResource(resource: URI): void { }
async setEncoding(encoding: string) { }
getEncoding() { return undefined; }
@@ -1474,6 +1521,12 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput
this.gotSavedAs = false;
this.dirty = false;
}
override toUntyped(): IUntypedEditorInput | undefined {
if (this.disableToUntyped) {
return undefined;
}
return { resource: this.resource };
}
setDirty(): void { this.dirty = true; }
override isDirty(): boolean {
return this.dirty;
@@ -1582,6 +1635,7 @@ export class TestWorkspacesService implements IWorkspacesService {
}
export class TestTerminalInstanceService implements ITerminalInstanceService {
onDidCreateInstance = Event.None;
declare readonly _serviceBrand: undefined;
async getXtermConstructor(): Promise<any> { throw new Error('Method not implemented.'); }
@@ -1589,6 +1643,7 @@ export class TestTerminalInstanceService implements ITerminalInstanceService {
async getXtermUnicode11Constructor(): Promise<any> { throw new Error('Method not implemented.'); }
async getXtermWebglConstructor(): Promise<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.'); }
createInstance(options: ICreateTerminalOptions, target?: TerminalLocation): ITerminalInstance { throw new Error('Method not implemented.'); }
}
export class TestTerminalProfileResolverService implements ITerminalProfileResolverService {
@@ -1612,10 +1667,10 @@ export class TestLocalTerminalService implements ILocalTerminalService {
onPtyHostUnresponsive = Event.None;
onPtyHostResponsive = Event.None;
onPtyHostRestart = Event.None;
onDidMoveWindowInstance = Event.None;
onDidRequestDetach = Event.None;
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise<ITerminalChildProcess> {
return new TestTerminalChildProcess(shouldPersist);
}
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, unicodeVersion: '6' | '11', env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise<ITerminalChildProcess> { return new TestTerminalChildProcess(shouldPersist); }
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.'); }
@@ -1629,6 +1684,8 @@ export class TestLocalTerminalService implements ILocalTerminalService {
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.'); }
requestDetachInstance(workspaceId: string, instanceId: number): Promise<IProcessDetails | undefined> { throw new Error('Method not implemented.'); }
acceptDetachInstanceReply(requestId: number, persistentProcessId: number): Promise<void> { throw new Error('Method not implemented.'); }
}
class TestTerminalChildProcess implements ITerminalChildProcess {
@@ -1649,6 +1706,7 @@ class TestTerminalChildProcess implements ITerminalChildProcess {
input(data: string): void { }
resize(cols: number, rows: number): void { }
acknowledgeDataEvent(charCount: number): void { }
async setUnicodeVersion(version: '6' | '11'): Promise<void> { }
async getInitialCwd(): Promise<string> { return ''; }
async getCwd(): Promise<string> { return ''; }
async getLatency(): Promise<number> { return 0; }

View File

@@ -14,6 +14,8 @@ suite('Memento', () => {
setup(() => {
storage = new TestStorageService();
Memento.clear(StorageScope.GLOBAL);
Memento.clear(StorageScope.WORKSPACE);
});
test('Loading and Saving Memento with Scopes', () => {
@@ -176,4 +178,30 @@ suite('Memento', () => {
memento = myMemento2.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE);
assert.deepStrictEqual(memento, { foo: 'Hello World', bar: 'Hello World' });
});
test('Clear Memento', () => {
let myMemento = new Memento('memento.test', storage);
// Global
let globalMemento = myMemento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
globalMemento.foo = 'Hello World';
// Workspace
let workspaceMemento = myMemento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE);
workspaceMemento.bar = 'Hello World';
myMemento.saveMemento();
// Clear
storage = new TestStorageService();
Memento.clear(StorageScope.GLOBAL);
Memento.clear(StorageScope.WORKSPACE);
myMemento = new Memento('memento.test', storage);
globalMemento = myMemento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
workspaceMemento = myMemento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE);
assert.deepStrictEqual(globalMemento, {});
assert.deepStrictEqual(workspaceMemento, {});
});
});

View File

@@ -16,12 +16,13 @@ import { isLinux, isMacintosh } from 'vs/base/common/platform';
import { InMemoryStorageService, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { IWorkingCopy, IWorkingCopyBackup, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopy';
import { NullExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent, IDeleteOperation, ICopyOperation, IMoveOperation, IFileOperationUndoRedoInfo, ICreateFileOperation, ICreateOperation } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent, IDeleteOperation, ICopyOperation, IMoveOperation, IFileOperationUndoRedoInfo, ICreateFileOperation, ICreateOperation, IStoredFileWorkingCopySaveParticipant } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { IFileStatWithMetadata } from 'vs/platform/files/common/files';
import { ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor';
import { ISaveOptions, IRevertOptions, SaveReason } from 'vs/workbench/common/editor';
import { CancellationToken } from 'vs/base/common/cancellation';
import product from 'vs/platform/product/common/product';
import { IActivity, IActivityService } from 'vs/workbench/services/activity/common/activity';
export class TestTextResourcePropertiesService implements ITextResourcePropertiesService {
@@ -33,8 +34,8 @@ export class TestTextResourcePropertiesService implements ITextResourcePropertie
}
getEOL(resource: URI, language?: string): string {
const eol = this.configurationService.getValue<string>('files.eol', { overrideIdentifier: language, resource });
if (eol && eol !== 'auto') {
const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource });
if (eol && typeof eol === 'string' && eol !== 'auto') {
return eol;
}
return (isLinux || isMacintosh) ? '\n' : '\r\n';
@@ -189,6 +190,10 @@ export class TestWorkingCopyFileService implements IWorkingCopyFileService {
addFileOperationParticipant(participant: IWorkingCopyFileOperationParticipant): IDisposable { return Disposable.None; }
readonly hasSaveParticipants = false;
addSaveParticipant(participant: IStoredFileWorkingCopySaveParticipant): IDisposable { return Disposable.None; }
async runSaveParticipants(workingCopy: IWorkingCopy, context: { reason: SaveReason; }, token: CancellationToken): Promise<void> { }
async delete(operations: IDeleteOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<void> { }
registerWorkingCopyProvider(provider: (resourceOrFolder: URI) => IWorkingCopy[]): IDisposable { return Disposable.None; }
@@ -214,3 +219,21 @@ export interface Ctor<T> {
export class TestExtensionService extends NullExtensionService { }
export const TestProductService = { _serviceBrand: undefined, ...product };
export class TestActivityService implements IActivityService {
_serviceBrand: undefined;
showViewContainerActivity(viewContainerId: string, badge: IActivity): IDisposable {
return this;
}
showViewActivity(viewId: string, badge: IActivity): IDisposable {
return this;
}
showAccountsActivity(activity: IActivity): IDisposable {
return this;
}
showGlobalActivity(activity: IActivity): IDisposable {
return this;
}
dispose() { }
}

View File

@@ -5,25 +5,25 @@
import * as assert from 'assert';
import { mapArrayOrNot } from 'vs/base/common/arrays';
import { timeout } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { joinPath } from 'vs/base/common/resources';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as pfs from 'vs/base/node/pfs';
import { MainContext, MainThreadSearchShape } from 'vs/workbench/api/common/extHost.protocol';
import { NativeExtHostSearch } from 'vs/workbench/api/node/extHostSearch';
import { Range } from 'vs/workbench/api/common/extHostTypes';
import { IFileMatch, IFileQuery, IPatternInfo, IRawFileMatch2, ISearchCompleteStats, ISearchQuery, ITextQuery, QueryType, resultIsMatch } from 'vs/workbench/services/search/common/search';
import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
import type * as vscode from 'vscode';
import { NullLogService } from 'vs/platform/log/common/log';
import { URITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
import { mock } from 'vs/base/test/common/mock';
import { NullLogService } from 'vs/platform/log/common/log';
import { MainContext, MainThreadSearchShape } from 'vs/workbench/api/common/extHost.protocol';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { Range } from 'vs/workbench/api/common/extHostTypes';
import { URITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
import { NativeExtHostSearch } from 'vs/workbench/api/node/extHostSearch';
import { IFileMatch, IFileQuery, IPatternInfo, IRawFileMatch2, ISearchCompleteStats, ISearchQuery, ITextQuery, QueryType, resultIsMatch } from 'vs/workbench/services/search/common/search';
import { TextSearchManager } from 'vs/workbench/services/search/common/textSearchManager';
import { NativeTextSearchManager } from 'vs/workbench/services/search/node/textSearchManager';
import { timeout } from 'vs/base/common/async';
import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
import type * as vscode from 'vscode';
let rpcProtocol: TestRPCProtocol;
let extHostSearch: NativeExtHostSearch;
@@ -141,7 +141,7 @@ suite('ExtHostSearch', () => {
constructor() {
super(
rpcProtocol,
new class extends mock<IExtHostInitDataService>() { remote = { isRemote: false, authority: undefined, connectionData: null }; },
new class extends mock<IExtHostInitDataService>() { override remote = { isRemote: false, authority: undefined, connectionData: null }; },
new URITransformerService(null),
logService
);