Initial VS Code 1.19 source merge (#571)

* Initial 1.19 xcopy

* Fix yarn build

* Fix numerous build breaks

* Next batch of build break fixes

* More build break fixes

* Runtime breaks

* Additional post merge fixes

* Fix windows setup file

* Fix test failures.

* Update license header blocks to refer to source eula
This commit is contained in:
Karl Burtram
2018-01-28 23:37:17 -08:00
committed by GitHub
parent 9a1ac20710
commit 251ae01c3e
8009 changed files with 93378 additions and 35634 deletions

View File

@@ -31,6 +31,8 @@ import { MainContext, ExtHostContext } from 'vs/workbench/api/node/extHost.proto
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import * as vscode from 'vscode';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import 'vs/workbench/parts/search/electron-browser/search.contribution';
import { NoopLogService } from 'vs/platform/log/common/log';
const defaultSelector = { scheme: 'far' };
const model: EditorCommon.IModel = EditorModel.createFromString(
@@ -112,7 +114,7 @@ suite('ExtHostLanguageFeatureCommands', function () {
const heapService = new ExtHostHeapService();
commands = new ExtHostCommands(threadService, heapService);
commands = new ExtHostCommands(threadService, heapService, new NoopLogService());
threadService.set(ExtHostContext.ExtHostCommands, commands);
threadService.setTestInstance(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, threadService));
ExtHostApiCommands.register(commands);
@@ -131,6 +133,7 @@ suite('ExtHostLanguageFeatureCommands', function () {
suiteTeardown(() => {
setUnexpectedErrorHandler(originalErrorHandler);
model.dispose();
mainThread.dispose();
});
teardown(function (done) {
@@ -193,6 +196,22 @@ suite('ExtHostLanguageFeatureCommands', function () {
}, done);
});
test('executeWorkspaceSymbolProvider should accept empty string, #39522', async function () {
disposables.push(extHost.registerWorkspaceSymbolProvider({
provideWorkspaceSymbols(query) {
return [new types.SymbolInformation('hello', types.SymbolKind.Array, new types.Range(0, 0, 0, 0), URI.parse('foo:bar'))];
}
}));
await threadService.sync();
let symbols = await commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeWorkspaceSymbolProvider', '');
assert.equal(symbols.length, 1);
await threadService.sync();
symbols = await commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeWorkspaceSymbolProvider', '*');
assert.equal(symbols.length, 1);
});
// --- definition
@@ -368,8 +387,8 @@ suite('ExtHostLanguageFeatureCommands', function () {
// --- quickfix
test('QuickFix, back and forth', function () {
disposables.push(extHost.registerCodeActionProvider(defaultSelector, <vscode.CodeActionProvider>{
provideCodeActions(): any {
disposables.push(extHost.registerCodeActionProvider(defaultSelector, {
provideCodeActions(): vscode.Command[] {
return [{ command: 'testing', title: 'Title', arguments: [1, 2, true] }];
}
}));

View File

@@ -12,6 +12,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { OneGetThreadService } from './testThreadService';
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { NoopLogService } from 'vs/platform/log/common/log';
suite('ExtHostCommands', function () {
@@ -29,7 +30,7 @@ suite('ExtHostCommands', function () {
}
};
const commands = new ExtHostCommands(OneGetThreadService(shape), undefined);
const commands = new ExtHostCommands(OneGetThreadService(shape), undefined, new NoopLogService());
commands.registerCommand('foo', (): any => { }).dispose();
assert.equal(lastUnregister, 'foo');
assert.equal(CommandsRegistry.getCommand('foo'), undefined);
@@ -50,7 +51,7 @@ suite('ExtHostCommands', function () {
}
};
const commands = new ExtHostCommands(OneGetThreadService(shape), undefined);
const commands = new ExtHostCommands(OneGetThreadService(shape), undefined, new NoopLogService());
const reg = commands.registerCommand('foo', (): any => { });
reg.dispose();
reg.dispose();

View File

@@ -25,7 +25,7 @@ suite('ExtHostConfiguration', function () {
this.lastArgs = [target, key, value];
return TPromise.as(void 0);
}
};
}
function createExtHostConfiguration(contents: any = Object.create(null), shape?: MainThreadConfigurationShape) {
if (!shape) {
@@ -91,6 +91,47 @@ suite('ExtHostConfiguration', function () {
assert.deepEqual(config.get('nested'), { config1: 42, config2: 'Das Pferd frisst kein Reis.' });
});
test('can modify the returned configuration', function () {
const all = createExtHostConfiguration({
'farboo': {
'config0': true,
'nested': {
'config1': 42,
'config2': 'Das Pferd frisst kein Reis.'
},
'config4': ''
}
});
let testObject = all.getConfiguration();
let actual = testObject.get('farboo');
actual['farboo1'] = 'newValue';
assert.equal('newValue', actual['farboo1']);
testObject = all.getConfiguration();
testObject['farboo']['farboo1'] = 'newValue';
assert.equal('newValue', testObject['farboo']['farboo1']);
testObject = all.getConfiguration();
testObject['farboo']['farboo1'] = 'newValue';
assert.equal('newValue', testObject.get('farboo')['farboo1']);
testObject = all.getConfiguration();
actual = testObject.inspect('farboo');
actual['value'] = 'effectiveValue';
assert.equal('effectiveValue', actual['value']);
testObject = all.getConfiguration();
actual = testObject.get('farboo');
assert.equal(undefined, actual['farboo1']);
testObject = all.getConfiguration();
testObject['farboo']['farboo1'] = 'newValue';
testObject = all.getConfiguration();
assert.equal(undefined, testObject['farboo']['farboo1']);
});
test('inspect in no workspace context', function () {
const testObject = new ExtHostConfiguration(
new class extends mock<MainThreadConfigurationShape>() { },

View File

@@ -24,7 +24,7 @@ suite('ExtHostDiagnostics', () => {
$clear(owner: string): TPromise<any> {
return TPromise.as(null);
}
};
}
test('disposeCheck', function () {
@@ -35,6 +35,7 @@ suite('ExtHostDiagnostics', () => {
assert.throws(() => collection.name);
assert.throws(() => collection.clear());
assert.throws(() => collection.delete(URI.parse('aa:bb')));
// tslint:disable-next-line:semicolon
assert.throws(() => collection.forEach(() => { ; }));
assert.throws(() => collection.get(URI.parse('aa:bb')));
assert.throws(() => collection.has(URI.parse('aa:bb')));

View File

@@ -42,18 +42,18 @@ suite('ExtHostDocumentData', () => {
});
test('readonly-ness', function () {
assert.throws(() => (<any>data).document.uri = null);
assert.throws(() => (<any>data).document.fileName = 'foofile');
assert.throws(() => (<any>data).document.isDirty = false);
assert.throws(() => (<any>data).document.isUntitled = false);
assert.throws(() => (<any>data).document.languageId = 'dddd');
assert.throws(() => (<any>data).document.lineCount = 9);
assert.throws((): void => (data as any).document.uri = null);
assert.throws(() => (data as any).document.fileName = 'foofile');
assert.throws(() => (data as any).document.isDirty = false);
assert.throws(() => (data as any).document.isUntitled = false);
assert.throws(() => (data as any).document.languageId = 'dddd');
assert.throws(() => (data as any).document.lineCount = 9);
});
test('save, when disposed', function () {
let saved: URI;
let data = new ExtHostDocumentData(new class extends mock<MainThreadDocumentsShape>() {
$trySaveDocument(uri) {
$trySaveDocument(uri: URI) {
assert.ok(!saved);
saved = uri;
return TPromise.as(true);

View File

@@ -24,26 +24,27 @@ import { MainThreadCommands } from 'vs/workbench/api/electron-browser/mainThread
import { IHeapService } from 'vs/workbench/api/electron-browser/mainThreadHeapService';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/common/quickOpen';
import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen';
import { DocumentSymbolProviderRegistry, DocumentHighlightKind, Hover } from 'vs/editor/common/modes';
import { getCodeLensData } from 'vs/editor/contrib/codelens/browser/codelens';
import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition } from 'vs/editor/contrib/goToDeclaration/browser/goToDeclaration';
import { getHover } from 'vs/editor/contrib/hover/common/hover';
import { getOccurrencesAtPosition } from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter';
import { provideReferences } from 'vs/editor/contrib/referenceSearch/browser/referenceSearch';
import { getCodeActions } from 'vs/editor/contrib/quickFix/browser/quickFix';
import { getCodeLensData } from 'vs/editor/contrib/codelens/codelens';
import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition } from 'vs/editor/contrib/goToDeclaration/goToDeclaration';
import { getHover } from 'vs/editor/contrib/hover/getHover';
import { getOccurrencesAtPosition } from 'vs/editor/contrib/wordHighlighter/wordHighlighter';
import { provideReferences } from 'vs/editor/contrib/referenceSearch/referenceSearch';
import { getCodeActions } from 'vs/editor/contrib/quickFix/quickFix';
import { getWorkspaceSymbols } from 'vs/workbench/parts/search/common/search';
import { rename } from 'vs/editor/contrib/rename/browser/rename';
import { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/common/parameterHints';
import { provideSuggestionItems } from 'vs/editor/contrib/suggest/browser/suggest';
import { getDocumentFormattingEdits, getDocumentRangeFormattingEdits, getOnTypeFormattingEdits } from 'vs/editor/contrib/format/common/format';
import { getLinks } from 'vs/editor/contrib/links/common/links';
import { rename } from 'vs/editor/contrib/rename/rename';
import { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
import { provideSuggestionItems } from 'vs/editor/contrib/suggest/suggest';
import { getDocumentFormattingEdits, getDocumentRangeFormattingEdits, getOnTypeFormattingEdits } from 'vs/editor/contrib/format/format';
import { getLinks } from 'vs/editor/contrib/links/getLinks';
import { asWinJsPromise } from 'vs/base/common/async';
import { MainContext, ExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import * as vscode from 'vscode';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { NoopLogService } from 'vs/platform/log/common/log';
const defaultSelector = { scheme: 'far' };
const model: EditorCommon.IModel = EditorModel.createFromString(
@@ -102,7 +103,7 @@ suite('ExtHostLanguageFeatures', function () {
const heapService = new ExtHostHeapService();
const commands = new ExtHostCommands(threadService, heapService);
const commands = new ExtHostCommands(threadService, heapService, new NoopLogService());
threadService.set(ExtHostContext.ExtHostCommands, commands);
threadService.setTestInstance(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, threadService));
@@ -118,6 +119,7 @@ suite('ExtHostLanguageFeatures', function () {
suiteTeardown(() => {
setUnexpectedErrorHandler(originalErrorHandler);
model.dispose();
mainThread.dispose();
});
teardown(function () {
@@ -641,11 +643,11 @@ suite('ExtHostLanguageFeatures', function () {
test('Quick Fix, data conversion', function () {
disposables.push(extHost.registerCodeActionProvider(defaultSelector, <vscode.CodeActionProvider>{
provideCodeActions(): any {
disposables.push(extHost.registerCodeActionProvider(defaultSelector, {
provideCodeActions(): vscode.Command[] {
return [
<vscode.Command>{ command: 'test1', title: 'Testing1' },
<vscode.Command>{ command: 'test2', title: 'Testing2' }
{ command: 'test1', title: 'Testing1' },
{ command: 'test2', title: 'Testing2' }
];
}
}));
@@ -654,11 +656,11 @@ suite('ExtHostLanguageFeatures', function () {
return getCodeActions(model, model.getFullModelRange()).then(value => {
assert.equal(value.length, 2);
let [first, second] = value;
const [first, second] = value;
assert.equal(first.title, 'Testing1');
assert.equal(first.id, 'test1');
assert.equal(first.command.id, 'test1');
assert.equal(second.title, 'Testing2');
assert.equal(second.id, 'test2');
assert.equal(second.command.id, 'test2');
});
});
});
@@ -732,6 +734,24 @@ suite('ExtHostLanguageFeatures', function () {
// --- rename
test('Rename, evil provider 0/2', function () {
disposables.push(extHost.registerRenameProvider(defaultSelector, <vscode.RenameProvider>{
provideRenameEdits(): any {
throw new class Foo { };
}
}));
return threadService.sync().then(() => {
return rename(model, new EditorPosition(1, 1), 'newName').then(value => {
throw Error();
}, err => {
// expected
});
});
});
test('Rename, evil provider 1/2', function () {
disposables.push(extHost.registerRenameProvider(defaultSelector, <vscode.RenameProvider>{
@@ -743,9 +763,7 @@ suite('ExtHostLanguageFeatures', function () {
return threadService.sync().then(() => {
return rename(model, new EditorPosition(1, 1), 'newName').then(value => {
throw new Error('');
}, err => {
// expected
assert.equal(value.rejectReason, 'evil');
});
});
});

View File

@@ -9,22 +9,23 @@ import * as assert from 'assert';
import { Action } from 'vs/base/common/actions';
import { MainThreadMessageService } from 'vs/workbench/api/electron-browser/mainThreadMessageService';
import { TPromise as Promise } from 'vs/base/common/winjs.base';
import { IMessageService, IChoiceService } from 'vs/platform/message/common/message';
suite('ExtHostMessageService', function () {
test('propagte handle on select', function () {
let service = new MainThreadMessageService(null, null, <any>{
show(sev: number, m: { message; actions: Action[] }) {
let service = new MainThreadMessageService(null, {
show(sev: number, m: { actions: Action[] }) {
assert.equal(m.actions.length, 1);
setImmediate(() => m.actions[0].run());
return () => { };
}
}, <any>{
choose() {
} as IMessageService, {
choose(severity, message, options, modal) {
throw new Error('not implemented');
}
});
} as IChoiceService);
return service.$showMessage(1, 'h', {}, [{ handle: 42, title: 'a thing', isCloseAffordance: true }]).then(handle => {
assert.equal(handle, 42);
@@ -34,15 +35,15 @@ suite('ExtHostMessageService', function () {
test('isCloseAffordance', function () {
let actions: Action[];
let service = new MainThreadMessageService(null, null, <any>{
show(sev: number, m: { message; actions: Action[] }) {
let service = new MainThreadMessageService(null, {
show(sev: number, m: { actions: Action[] }) {
actions = m.actions;
}
}, <any>{
choose() {
} as IMessageService, {
choose(severity, message, options, modal) {
throw new Error('not implemented');
}
});
} as IChoiceService);
// default close action
service.$showMessage(1, '', {}, [{ title: 'a thing', isCloseAffordance: false, handle: 0 }]);
@@ -62,19 +63,19 @@ suite('ExtHostMessageService', function () {
let actions: Action[];
let c: number;
let service = new MainThreadMessageService(null, null, <any>{
show(sev: number, m: { message; actions: Action[] }) {
let service = new MainThreadMessageService(null, {
show(sev: number, m: { actions: Action[] }) {
c = 0;
actions = m.actions;
return () => {
c += 1;
};
}
}, <any>{
choose() {
} as IMessageService, {
choose(severity, message, options, modal) {
throw new Error('not implemented');
}
});
} as IChoiceService);
service.$showMessage(1, '', {}, [{ title: 'a thing', isCloseAffordance: true, handle: 0 }]);
assert.equal(actions.length, 1);
@@ -85,11 +86,11 @@ suite('ExtHostMessageService', function () {
suite('modal', () => {
test('calls choice service', () => {
const service = new MainThreadMessageService(null, null, <any>{
show(sev: number, m: { message; actions: Action[] }) {
const service = new MainThreadMessageService(null, {
show(sev: number, m: { actions: Action[] }) {
throw new Error('not implemented');
}
}, <any>{
} as IMessageService, {
choose(severity, message, options, modal) {
assert.equal(severity, 1);
assert.equal(message, 'h');
@@ -97,7 +98,7 @@ suite('ExtHostMessageService', function () {
assert.equal(options[1], 'Cancel');
return Promise.as(0);
}
});
} as IChoiceService);
return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: false }]).then(handle => {
assert.equal(handle, 42);
@@ -105,15 +106,15 @@ suite('ExtHostMessageService', function () {
});
test('returns undefined when cancelled', () => {
const service = new MainThreadMessageService(null, null, <any>{
show(sev: number, m: { message; actions: Action[] }) {
const service = new MainThreadMessageService(null, {
show(sev: number, m: { actions: Action[] }) {
throw new Error('not implemented');
}
}, <any>{
} as IMessageService, {
choose(severity, message, options, modal) {
return Promise.as(1);
}
});
} as IChoiceService);
return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: false }]).then(handle => {
assert.equal(handle, undefined);
@@ -121,16 +122,16 @@ suite('ExtHostMessageService', function () {
});
test('hides Cancel button when not needed', () => {
const service = new MainThreadMessageService(null, null, <any>{
show(sev: number, m: { message; actions: Action[] }) {
const service = new MainThreadMessageService(null, {
show(sev: number, m: { actions: Action[] }) {
throw new Error('not implemented');
}
}, <any>{
} as IMessageService, {
choose(severity, message, options, modal) {
assert.equal(options.length, 1);
return Promise.as(0);
}
});
} as IChoiceService);
return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: true }]).then(handle => {
assert.equal(handle, 42);

View File

@@ -17,27 +17,45 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
import { MainThreadCommands } from 'vs/workbench/api/electron-browser/mainThreadCommands';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { TPromise } from 'vs/base/common/winjs.base';
import { TreeItemCollapsibleState, ITreeItem } from 'vs/workbench/common/views';
import { NoopLogService } from 'vs/platform/log/common/log';
suite('ExtHostConfiguration', function () {
suite('ExtHostTreeView', function () {
class RecordingShape extends mock<MainThreadTreeViewsShape>() {
onRefresh = new Emitter<number[]>();
onRefresh = new Emitter<{ [treeItemHandle: string]: ITreeItem }>();
$registerView(treeViewId: string): void {
}
$refresh(viewId: string, itemHandles: number[]): void {
this.onRefresh.fire(itemHandles);
$refresh(viewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): void {
this.onRefresh.fire(itemsToRefresh);
}
};
}
let testObject: ExtHostTreeViews;
let target: RecordingShape;
let onDidChangeTreeData: Emitter<string>;
let onDidChangeTreeNode: Emitter<{ key: string }>;
let onDidChangeTreeKey: Emitter<string>;
let tree, labels, nodes;
setup(() => {
tree = {
'a': {
'aa': {},
'ab': {}
},
'b': {
'ba': {},
'bb': {}
}
};
labels = {};
nodes = {};
let threadService = new TestThreadService();
// Use IInstantiationService to get typechecking when instantiating
let inst: IInstantiationService;
@@ -48,97 +66,307 @@ suite('ExtHostConfiguration', function () {
threadService.setTestInstance(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, threadService));
target = new RecordingShape();
testObject = new ExtHostTreeViews(target, new ExtHostCommands(threadService, new ExtHostHeapService()));
onDidChangeTreeData = new Emitter<string>();
testObject.registerTreeDataProvider('testDataProvider', aTreeDataProvider());
testObject = new ExtHostTreeViews(target, new ExtHostCommands(threadService, new ExtHostHeapService(), new NoopLogService()));
onDidChangeTreeNode = new Emitter<{ key: string }>();
onDidChangeTreeKey = new Emitter<string>();
testObject.registerTreeDataProvider('testNodeTreeProvider', aNodeTreeDataProvider());
testObject.registerTreeDataProvider('testStringTreeProvider', aStringTreeDataProvider());
testObject.$getElements('testDataProvider').then(elements => {
testObject.$getElements('testNodeTreeProvider').then(elements => {
for (const element of elements) {
testObject.$getChildren('testDataProvider', element.handle);
testObject.$getChildren('testNodeTreeProvider', element.handle);
}
});
});
test('refresh calls are throttled on roots', function (done) {
test('construct node tree', () => {
return testObject.$getElements('testNodeTreeProvider')
.then(elements => {
const actuals = elements.map(e => e.handle);
assert.deepEqual(actuals, ['0/0:a', '0/1:b']);
return TPromise.join([
testObject.$getChildren('testNodeTreeProvider', '0/0:a')
.then(children => {
const actuals = children.map(e => e.handle);
assert.deepEqual(actuals, ['0/0:a/0:aa', '0/0:a/1:ab']);
return TPromise.join([
testObject.$getChildren('testNodeTreeProvider', '0/0:a/0:aa').then(children => assert.equal(children.length, 0)),
testObject.$getChildren('testNodeTreeProvider', '0/0:a/1:ab').then(children => assert.equal(children.length, 0))
]);
}),
testObject.$getChildren('testNodeTreeProvider', '0/1:b')
.then(children => {
const actuals = children.map(e => e.handle);
assert.deepEqual(actuals, ['0/1:b/0:ba', '0/1:b/1:bb']);
return TPromise.join([
testObject.$getChildren('testNodeTreeProvider', '0/1:b/0:ba').then(children => assert.equal(children.length, 0)),
testObject.$getChildren('testNodeTreeProvider', '0/1:b/1:bb').then(children => assert.equal(children.length, 0))
]);
})
]);
});
});
test('construct string tree', () => {
return testObject.$getElements('testStringTreeProvider')
.then(elements => {
const actuals = elements.map(e => e.handle);
assert.deepEqual(actuals, ['a', 'b']);
return TPromise.join([
testObject.$getChildren('testStringTreeProvider', 'a')
.then(children => {
const actuals = children.map(e => e.handle);
assert.deepEqual(actuals, ['aa', 'ab']);
return TPromise.join([
testObject.$getChildren('testStringTreeProvider', 'aa').then(children => assert.equal(children.length, 0)),
testObject.$getChildren('testStringTreeProvider', 'ab').then(children => assert.equal(children.length, 0))
]);
}),
testObject.$getChildren('testStringTreeProvider', 'b')
.then(children => {
const actuals = children.map(e => e.handle);
assert.deepEqual(actuals, ['ba', 'bb']);
return TPromise.join([
testObject.$getChildren('testStringTreeProvider', 'ba').then(children => assert.equal(children.length, 0)),
testObject.$getChildren('testStringTreeProvider', 'bb').then(children => assert.equal(children.length, 0))
]);
})
]);
});
});
test('refresh root', function (done) {
target.onRefresh.event(actuals => {
assert.equal(0, actuals.length);
assert.equal(undefined, actuals);
done();
});
onDidChangeTreeData.fire();
onDidChangeTreeData.fire();
onDidChangeTreeData.fire();
onDidChangeTreeData.fire();
onDidChangeTreeNode.fire();
});
test('refresh a parent node', () => {
return new TPromise((c, e) => {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/1:b'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/1:b']), {
handle: '0/1:b',
label: 'b',
});
c(null);
});
onDidChangeTreeNode.fire(getNode('b'));
});
});
test('refresh a leaf node', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/1:b/1:bb'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/1:b/1:bb']), {
handle: '0/1:b/1:bb',
parentHandle: '0/1:b',
label: 'bb'
});
done();
});
onDidChangeTreeNode.fire(getNode('bb'));
});
test('refresh parent and child node trigger refresh only on parent - scenario 1', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/1:b', '0/0:a/0:aa'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/1:b']), {
handle: '0/1:b',
label: 'b',
});
assert.deepEqual(removeUnsetKeys(actuals['0/0:a/0:aa']), {
handle: '0/0:a/0:aa',
parentHandle: '0/0:a',
label: 'aa',
});
done();
});
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('aa'));
onDidChangeTreeNode.fire(getNode('bb'));
});
test('refresh parent and child node trigger refresh only on parent - scenario 2', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:a/0:aa', '0/1:b'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/1:b']), {
handle: '0/1:b',
label: 'b',
});
assert.deepEqual(removeUnsetKeys(actuals['0/0:a/0:aa']), {
handle: '0/0:a/0:aa',
parentHandle: '0/0:a',
label: 'aa',
});
done();
});
onDidChangeTreeNode.fire(getNode('bb'));
onDidChangeTreeNode.fire(getNode('aa'));
onDidChangeTreeNode.fire(getNode('b'));
});
test('refresh an element for label change', function (done) {
labels['a'] = 'aa';
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:a'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/0:a']), {
handle: '0/0:aa',
label: 'aa',
});
done();
});
onDidChangeTreeNode.fire(getNode('a'));
});
test('refresh calls are throttled on roots', function (done) {
target.onRefresh.event(actuals => {
assert.equal(undefined, actuals);
done();
});
onDidChangeTreeNode.fire();
onDidChangeTreeNode.fire();
onDidChangeTreeNode.fire();
onDidChangeTreeNode.fire();
});
test('refresh calls are throttled on elements', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual([1, 2], actuals);
assert.deepEqual(['0/0:a', '0/1:b'], Object.keys(actuals));
done();
});
onDidChangeTreeData.fire('a');
onDidChangeTreeData.fire('b');
onDidChangeTreeData.fire('b');
onDidChangeTreeData.fire('a');
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('a'));
});
test('refresh calls are throttled on unknown elements', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual([1, 2], actuals);
assert.deepEqual(['0/0:a', '0/1:b'], Object.keys(actuals));
done();
});
onDidChangeTreeData.fire('a');
onDidChangeTreeData.fire('b');
onDidChangeTreeData.fire('g');
onDidChangeTreeData.fire('a');
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('g'));
onDidChangeTreeNode.fire(getNode('a'));
});
test('refresh calls are throttled on unknown elements and root', function (done) {
target.onRefresh.event(actuals => {
assert.equal(0, actuals.length);
assert.equal(undefined, actuals);
done();
});
onDidChangeTreeData.fire('a');
onDidChangeTreeData.fire('b');
onDidChangeTreeData.fire('g');
onDidChangeTreeData.fire('');
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('g'));
onDidChangeTreeNode.fire();
});
test('refresh calls are throttled on elements and root', function (done) {
target.onRefresh.event(actuals => {
assert.equal(0, actuals.length);
assert.equal(undefined, actuals);
done();
});
onDidChangeTreeData.fire('a');
onDidChangeTreeData.fire('b');
onDidChangeTreeData.fire();
onDidChangeTreeData.fire('a');
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire();
onDidChangeTreeNode.fire(getNode('a'));
});
function aTreeDataProvider(): TreeDataProvider<string> {
return <TreeDataProvider<string>>{
getChildren: (element: string): string[] => {
if (!element) {
return ['a', 'b'];
}
if (element === 'a') {
return ['aa', 'ab'];
}
if (element === 'b') {
return ['ba', 'bb'];
}
return [];
test('generate unique handles from labels by escaping them', () => {
tree = {
'a/0:b': {}
};
onDidChangeTreeNode.fire();
return testObject.$getElements('testNodeTreeProvider')
.then(elements => {
assert.deepEqual(elements.map(e => e.handle), ['0/0:a//0:b']);
});
});
function removeUnsetKeys(obj: any): any {
const result = {};
for (const key of Object.keys(obj)) {
if (obj[key] !== void 0) {
result[key] = obj[key];
}
}
return result;
}
function aNodeTreeDataProvider(): TreeDataProvider<{ key: string }> {
return {
getChildren: (element: { key: string }): { key: string }[] => {
return getChildren(element ? element.key : undefined).map(key => getNode(key));
},
getTreeItem: (element: string): TreeItem => {
return <TreeItem>{
label: element
};
getTreeItem: (element: { key: string }): TreeItem => {
return getTreeItem(element.key);
},
onDidChangeTreeData: onDidChangeTreeData.event
onDidChangeTreeData: onDidChangeTreeNode.event
};
}
function aStringTreeDataProvider(): TreeDataProvider<string> {
return {
getChildren: (element: string): string[] => {
return getChildren(element);
},
getTreeItem: (element: string): TreeItem => {
return getTreeItem(element);
},
onDidChangeTreeData: onDidChangeTreeKey.event
};
}
function getTreeElement(element): any {
let parent = tree;
for (let i = 0; i < element.length; i++) {
parent = parent[element.substring(0, i + 1)];
if (!parent) {
return null;
}
}
return parent;
}
function getChildren(key: string): string[] {
if (!key) {
return Object.keys(tree);
}
let treeElement = getTreeElement(key);
if (treeElement) {
const children = Object.keys(treeElement);
const collapsibleStateIndex = children.indexOf('collapsibleState');
if (collapsibleStateIndex !== -1) {
children.splice(collapsibleStateIndex, 1);
}
return children;
}
return [];
}
function getTreeItem(key: string): TreeItem {
const treeElement = getTreeElement(key);
return {
label: labels[key] || key,
collapsibleState: treeElement ? treeElement['collapsibleState'] : TreeItemCollapsibleState.Collapsed
};
}
function getNode(key: string): { key: string } {
if (!nodes[key]) {
nodes[key] = { key };
}
return nodes[key];
}
});

View File

@@ -25,16 +25,13 @@ suite('ExtHostWorkspace', function () {
}
test('asRelativePath', function () {
// const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/Applications/NewsWoWBot'), 0)], name: 'Test' });
// assertAsRelativePath(ws, '/Coding/Applications/NewsWoWBot/bernd/das/brot', 'bernd/das/brot');
// assertAsRelativePath(ws, '/Apps/DartPubCache/hosted/pub.dartlang.org/convert-2.0.1/lib/src/hex.dart',
// '/Apps/DartPubCache/hosted/pub.dartlang.org/convert-2.0.1/lib/src/hex.dart');
// assertAsRelativePath(ws, '', '');
// assertAsRelativePath(ws, '/foo/bar', '/foo/bar');
// assertAsRelativePath(ws, 'in/out', 'in/out');
});
function aWorkspaceFolderData(uri: URI, index: number, name: string = ''): IWorkspaceFolderData {
return {
uri,
index,
name: name || basename(uri.path)
};
}
});

View File

@@ -10,11 +10,11 @@ import { MainThreadDocumentsAndEditors } from 'vs/workbench/api/electron-browser
import { OneGetThreadService } from './testThreadService';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { MockCodeEditorService } from 'vs/editor/test/common/mocks/mockCodeEditorService';
import { TestCodeEditorService } from 'vs/editor/test/browser/testCodeEditorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta } from 'vs/workbench/api/node/extHost.protocol';
import { mockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import Event from 'vs/base/common/event';
@@ -22,10 +22,9 @@ import Event from 'vs/base/common/event';
suite('MainThreadDocumentsAndEditors', () => {
let modelService: ModelServiceImpl;
let codeEditorService: MockCodeEditorService;
let codeEditorService: TestCodeEditorService;
let textFileService: ITextFileService;
let workbenchEditorService: IWorkbenchEditorService;
let documentAndEditor: MainThreadDocumentsAndEditors;
let deltas: IDocumentsAndEditorsDelta[] = [];
const hugeModelString = new Array(2 + (50 * 1024 * 1024)).join('-');
@@ -34,9 +33,9 @@ suite('MainThreadDocumentsAndEditors', () => {
const configService = new TestConfigurationService();
configService.setUserConfiguration('editor', { 'detectIndentation': false });
modelService = new ModelServiceImpl(null, configService);
codeEditorService = new MockCodeEditorService();
codeEditorService = new TestCodeEditorService();
textFileService = new class extends mock<ITextFileService>() {
isDirty() { return false; };
isDirty() { return false; }
models = <any>{
onModelSaved: Event.None,
onModelReverted: Event.None,
@@ -52,7 +51,8 @@ suite('MainThreadDocumentsAndEditors', () => {
onEditorGroupMoved = Event.None;
};
documentAndEditor = new MainThreadDocumentsAndEditors(
/* tslint:disable */
new MainThreadDocumentsAndEditors(
OneGetThreadService(new class extends mock<ExtHostDocumentsAndEditorsShape>() {
$acceptDocumentsAndEditorsDelta(delta) { deltas.push(delta); }
}),
@@ -65,8 +65,8 @@ suite('MainThreadDocumentsAndEditors', () => {
null,
null,
editorGroupService,
null
);
/* tslint:enable */
});
@@ -104,7 +104,7 @@ suite('MainThreadDocumentsAndEditors', () => {
this.timeout(1000 * 60); // increase timeout for this one test
const model = modelService.createModel(hugeModelString, null, null);
const editor = mockCodeEditor(null, { model, wordWrap: 'off', wordWrapMinified: false });
const editor = createTestCodeEditor(model);
assert.equal(deltas.length, 1);
deltas.length = 0;
@@ -113,7 +113,7 @@ suite('MainThreadDocumentsAndEditors', () => {
});
test('ignore editor w/o model', () => {
const editor = mockCodeEditor([], {});
const editor = createTestCodeEditor(null);
editor.setModel(null);
codeEditorService.addCodeEditor(editor);
assert.equal(deltas.length, 1);
@@ -129,7 +129,7 @@ suite('MainThreadDocumentsAndEditors', () => {
deltas.length = 0;
const model = modelService.createModel('farboo', null, null);
codeEditorService.addCodeEditor(mockCodeEditor(null, { model }));
codeEditorService.addCodeEditor(createTestCodeEditor(model));
assert.equal(deltas.length, 2);
const [first, second] = deltas;
@@ -149,7 +149,7 @@ suite('MainThreadDocumentsAndEditors', () => {
test('editor with dispos-ed/-ing model', () => {
modelService.createModel('foobar', null, null);
const model = modelService.createModel('farboo', null, null);
const editor = mockCodeEditor(null, { model });
const editor = createTestCodeEditor(model);
codeEditorService.addCodeEditor(editor);
// ignore things until now
@@ -158,6 +158,7 @@ suite('MainThreadDocumentsAndEditors', () => {
modelService.destroyModel(model.uri);
assert.equal(deltas.length, 1);
const [first] = deltas;
assert.equal(first.newActiveEditor, null);
assert.equal(first.removedEditors.length, 1);
assert.equal(first.removedDocuments.length, 1);

View File

@@ -10,7 +10,7 @@ import { MainThreadDocumentsAndEditors } from 'vs/workbench/api/electron-browser
import { OneGetThreadService, TestThreadService } from './testThreadService';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { MockCodeEditorService } from 'vs/editor/test/common/mocks/mockCodeEditorService';
import { TestCodeEditorService } from 'vs/editor/test/browser/testCodeEditorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ExtHostDocumentsAndEditorsShape, IWorkspaceResourceEdit, ExtHostContext, ExtHostDocumentsShape } from 'vs/workbench/api/node/extHost.protocol';
@@ -34,9 +34,9 @@ suite('MainThreadEditors', () => {
setup(() => {
const configService = new TestConfigurationService();
modelService = new ModelServiceImpl(null, configService);
const codeEditorService = new MockCodeEditorService();
const codeEditorService = new TestCodeEditorService();
const textFileService = new class extends mock<ITextFileService>() {
isDirty() { return false; };
isDirty() { return false; }
models = <any>{
onModelSaved: Event.None,
onModelReverted: Event.None,
@@ -73,7 +73,6 @@ suite('MainThreadEditors', () => {
null,
null,
editorGroupService,
null
);
editors = new MainThreadEditors(
@@ -84,7 +83,6 @@ suite('MainThreadEditors', () => {
editorGroupService,
null,
null,
null,
modelService
);
});

View File

@@ -10,5 +10,5 @@ export interface Ctor<T> {
}
export function mock<T>(): Ctor<T> {
return <any>function () { };
return function () { } as any;
}