Merge VS Code 1.23.1 (#1520)

This commit is contained in:
Matt Irvine
2018-06-05 11:24:51 -07:00
committed by GitHub
parent e3baf5c443
commit 0c58f09e59
3651 changed files with 74249 additions and 48599 deletions

View File

@@ -33,6 +33,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import 'vs/workbench/parts/search/electron-browser/search.contribution';
import { NullLogService } from 'vs/platform/log/common/log';
import { ITextModel } from 'vs/editor/common/model';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { generateUuid } from 'vs/base/common/uuid';
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
const defaultSelector = { scheme: 'far' };
const model: ITextModel = EditorModel.createFromString(
@@ -49,12 +52,14 @@ let rpcProtocol: TestRPCProtocol;
let extHost: ExtHostLanguageFeatures;
let mainThread: MainThreadLanguageFeatures;
let commands: ExtHostCommands;
let task: ExtHostTask;
let workspace: ExtHostWorkspace;
let disposables: vscode.Disposable[] = [];
let originalErrorHandler: (e: any) => any;
suite('ExtHostLanguageFeatureCommands', function () {
suiteSetup((done) => {
suiteSetup(() => {
originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
setUnexpectedErrorHandler(() => { });
@@ -115,19 +120,21 @@ suite('ExtHostLanguageFeatureCommands', function () {
const heapService = new ExtHostHeapService();
commands = new ExtHostCommands(rpcProtocol, heapService, new NullLogService());
workspace = new ExtHostWorkspace(rpcProtocol, { id: generateUuid(), name: 'Test', folders: [] }, new NullLogService());
task = new ExtHostTask(rpcProtocol, workspace);
rpcProtocol.set(ExtHostContext.ExtHostCommands, commands);
rpcProtocol.set(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, rpcProtocol));
ExtHostApiCommands.register(commands);
ExtHostApiCommands.register(commands, task);
const diagnostics = new ExtHostDiagnostics(rpcProtocol);
rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
extHost = new ExtHostLanguageFeatures(rpcProtocol, extHostDocuments, commands, heapService, diagnostics);
extHost = new ExtHostLanguageFeatures(rpcProtocol, null, extHostDocuments, commands, heapService, diagnostics);
rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost);
mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, inst.createInstance(MainThreadLanguageFeatures, rpcProtocol));
rpcProtocol.sync().then(done, done);
return rpcProtocol.sync();
});
suiteTeardown(() => {
@@ -136,17 +143,16 @@ suite('ExtHostLanguageFeatureCommands', function () {
mainThread.dispose();
});
teardown(function (done) {
teardown(function () {
while (disposables.length) {
disposables.pop().dispose();
}
rpcProtocol.sync()
.then(() => done(), err => done(err));
return rpcProtocol.sync();
});
// --- workspace symbols
test('WorkspaceSymbols, invalid arguments', function (done) {
test('WorkspaceSymbols, invalid arguments', function () {
let promises = [
commands.executeCommand('vscode.executeWorkspaceSymbolProvider'),
commands.executeCommand('vscode.executeWorkspaceSymbolProvider', null),
@@ -154,14 +160,12 @@ suite('ExtHostLanguageFeatureCommands', function () {
commands.executeCommand('vscode.executeWorkspaceSymbolProvider', true)
];
TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
return TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
assert.equal(err.length, 4);
done();
return [];
});
});
test('WorkspaceSymbols, back and forth', function (done) {
test('WorkspaceSymbols, back and forth', function () {
disposables.push(extHost.registerWorkspaceSymbolProvider(<vscode.WorkspaceSymbolProvider>{
provideWorkspaceSymbols(query): any {
@@ -180,8 +184,8 @@ suite('ExtHostLanguageFeatureCommands', function () {
}
}));
rpcProtocol.sync().then(() => {
commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeWorkspaceSymbolProvider', 'testing').then(value => {
return rpcProtocol.sync().then(() => {
return commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeWorkspaceSymbolProvider', 'testing').then(value => {
for (let info of value) {
assert.ok(info instanceof types.SymbolInformation);
@@ -189,9 +193,8 @@ suite('ExtHostLanguageFeatureCommands', function () {
assert.equal(info.kind, types.SymbolKind.Array);
}
assert.equal(value.length, 3);
done();
}, done);
}, done);
});
});
});
test('executeWorkspaceSymbolProvider should accept empty string, #39522', async function () {
@@ -213,7 +216,7 @@ suite('ExtHostLanguageFeatureCommands', function () {
// --- definition
test('Definition, invalid arguments', function (done) {
test('Definition, invalid arguments', function () {
let promises = [
commands.executeCommand('vscode.executeDefinitionProvider'),
commands.executeCommand('vscode.executeDefinitionProvider', null),
@@ -221,10 +224,8 @@ suite('ExtHostLanguageFeatureCommands', function () {
commands.executeCommand('vscode.executeDefinitionProvider', true, false)
];
TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
return TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
assert.equal(err.length, 4);
done();
return [];
});
});
@@ -256,6 +257,49 @@ suite('ExtHostLanguageFeatureCommands', function () {
});
});
// --- type definition
test('Type Definition, invalid arguments', function () {
const promises = [
commands.executeCommand('vscode.executeTypeDefinitionProvider'),
commands.executeCommand('vscode.executeTypeDefinitionProvider', null),
commands.executeCommand('vscode.executeTypeDefinitionProvider', undefined),
commands.executeCommand('vscode.executeTypeDefinitionProvider', true, false)
];
return TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
assert.equal(err.length, 4);
});
});
test('Type Definition, back and forth', function () {
disposables.push(extHost.registerTypeDefinitionProvider(defaultSelector, <vscode.TypeDefinitionProvider>{
provideTypeDefinition(doc: any): any {
return new types.Location(doc.uri, new types.Range(0, 0, 0, 0));
}
}));
disposables.push(extHost.registerTypeDefinitionProvider(defaultSelector, <vscode.TypeDefinitionProvider>{
provideTypeDefinition(doc: any): any {
return [
new types.Location(doc.uri, new types.Range(0, 0, 0, 0)),
new types.Location(doc.uri, new types.Range(0, 0, 0, 0)),
new types.Location(doc.uri, new types.Range(0, 0, 0, 0)),
];
}
}));
return rpcProtocol.sync().then(() => {
return commands.executeCommand<vscode.Location[]>('vscode.executeTypeDefinitionProvider', model.uri, new types.Position(0, 0)).then(values => {
assert.equal(values.length, 4);
for (const v of values) {
assert.ok(v.uri instanceof URI);
assert.ok(v.range instanceof types.Range);
}
});
});
});
// --- references
test('reference search, back and forth', function () {
@@ -281,7 +325,7 @@ suite('ExtHostLanguageFeatureCommands', function () {
// --- outline
test('Outline, back and forth', function (done) {
test('Outline, back and forth', function () {
disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, <vscode.DocumentSymbolProvider>{
provideDocumentSymbols(): any {
return [
@@ -291,15 +335,14 @@ suite('ExtHostLanguageFeatureCommands', function () {
}
}));
rpcProtocol.sync().then(() => {
commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeDocumentSymbolProvider', model.uri).then(values => {
return rpcProtocol.sync().then(() => {
return commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeDocumentSymbolProvider', model.uri).then(values => {
assert.equal(values.length, 2);
let [first, second] = values;
assert.equal(first.name, 'testing2');
assert.equal(second.name, 'testing1');
done();
}, done);
}, done);
});
});
});
// --- suggest
@@ -362,7 +405,7 @@ suite('ExtHostLanguageFeatureCommands', function () {
});
});
test('Suggest, return CompletionList !array', function (done) {
test('Suggest, return CompletionList !array', function () {
disposables.push(extHost.registerCompletionItemProvider(defaultSelector, <vscode.CompletionItemProvider>{
provideCompletionItems(): any {
let a = new types.CompletionItem('item1');
@@ -371,15 +414,47 @@ suite('ExtHostLanguageFeatureCommands', function () {
}
}, []));
rpcProtocol.sync().then(() => {
return rpcProtocol.sync().then(() => {
return commands.executeCommand<vscode.CompletionList>('vscode.executeCompletionItemProvider', model.uri, new types.Position(0, 4)).then(list => {
assert.ok(list instanceof types.CompletionList);
assert.equal(list.isIncomplete, true);
done();
});
});
});
test('Suggest, resolve completion items', async function () {
let resolveCount = 0;
disposables.push(extHost.registerCompletionItemProvider(defaultSelector, <vscode.CompletionItemProvider>{
provideCompletionItems(): any {
let a = new types.CompletionItem('item1');
let b = new types.CompletionItem('item2');
let c = new types.CompletionItem('item3');
let d = new types.CompletionItem('item4');
return new types.CompletionList([a, b, c, d], false);
},
resolveCompletionItem(item) {
resolveCount += 1;
return item;
}
}, []));
await rpcProtocol.sync();
let list = await commands.executeCommand<vscode.CompletionList>(
'vscode.executeCompletionItemProvider',
model.uri,
new types.Position(0, 4),
undefined,
2 // maxItemsToResolve
);
assert.ok(list instanceof types.CompletionList);
assert.equal(resolveCount, 2);
});
// --- quickfix
test('QuickFix, back and forth', function () {
@@ -459,6 +534,40 @@ suite('ExtHostLanguageFeatureCommands', function () {
});
});
test('CodeLens, resolve', async function () {
let resolveCount = 0;
disposables.push(extHost.registerCodeLensProvider(defaultSelector, <vscode.CodeLensProvider>{
provideCodeLenses(): any {
return [
new types.CodeLens(new types.Range(0, 0, 1, 1)),
new types.CodeLens(new types.Range(0, 0, 1, 1)),
new types.CodeLens(new types.Range(0, 0, 1, 1)),
new types.CodeLens(new types.Range(0, 0, 1, 1), { title: 'Already resolved', command: 'fff' })
];
},
resolveCodeLens(codeLens: types.CodeLens) {
codeLens.command = { title: resolveCount.toString(), command: 'resolved' };
resolveCount += 1;
return codeLens;
}
}));
await rpcProtocol.sync();
let value = await commands.executeCommand<vscode.CodeLens[]>('vscode.executeCodeLensProvider', model.uri, 2);
assert.equal(value.length, 3); // the resolve argument defines the number of results being returned
assert.equal(resolveCount, 2);
resolveCount = 0;
value = await commands.executeCommand<vscode.CodeLens[]>('vscode.executeCodeLensProvider', model.uri);
assert.equal(value.length, 4);
assert.equal(resolveCount, 0);
});
test('Links, back and forth', function () {
disposables.push(extHost.registerDocumentLinkProvider(defaultSelector, <vscode.DocumentLinkProvider>{
@@ -480,4 +589,55 @@ suite('ExtHostLanguageFeatureCommands', function () {
});
});
});
test('Color provider', function () {
disposables.push(extHost.registerColorProvider(defaultSelector, <vscode.DocumentColorProvider>{
provideDocumentColors(): vscode.ColorInformation[] {
return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))];
},
provideColorPresentations(color: vscode.Color, context: { range: vscode.Range, document: vscode.TextDocument }): vscode.ColorPresentation[] {
const cp = new types.ColorPresentation('#ABC');
cp.textEdit = types.TextEdit.replace(new types.Range(1, 0, 1, 20), '#ABC');
cp.additionalTextEdits = [types.TextEdit.insert(new types.Position(2, 20), '*')];
return [cp];
}
}));
return rpcProtocol.sync().then(() => {
return commands.executeCommand<vscode.ColorInformation[]>('vscode.executeDocumentColorProvider', model.uri).then(value => {
assert.equal(value.length, 1);
let [first] = value;
assert.equal(first.color.red, 0.1);
assert.equal(first.color.green, 0.2);
assert.equal(first.color.blue, 0.3);
assert.equal(first.color.alpha, 0.4);
assert.equal(first.range.start.line, 0);
assert.equal(first.range.start.character, 0);
assert.equal(first.range.end.line, 0);
assert.equal(first.range.end.character, 20);
});
}).then(() => {
const color = new types.Color(0.5, 0.6, 0.7, 0.8);
const range = new types.Range(0, 0, 0, 20);
return commands.executeCommand<vscode.ColorPresentation[]>('vscode.executeColorPresentationProvider', color, { uri: model.uri, range }).then(value => {
assert.equal(value.length, 1);
let [first] = value;
assert.equal(first.label, '#ABC');
assert.equal(first.textEdit.newText, '#ABC');
assert.equal(first.textEdit.range.start.line, 1);
assert.equal(first.textEdit.range.start.character, 0);
assert.equal(first.textEdit.range.end.line, 1);
assert.equal(first.textEdit.range.end.character, 20);
assert.equal(first.additionalTextEdits.length, 1);
assert.equal(first.additionalTextEdits[0].range.start.line, 2);
assert.equal(first.additionalTextEdits[0].range.start.character, 20);
assert.equal(first.additionalTextEdits[0].range.end.line, 2);
assert.equal(first.additionalTextEdits[0].range.end.character, 20);
});
});
});
});

View File

@@ -29,7 +29,7 @@ suite('ExtHostCommands', function () {
};
const commands = new ExtHostCommands(SingleProxyRPCProtocol(shape), undefined, new NullLogService());
commands.registerCommand('foo', (): any => { }).dispose();
commands.registerCommand(true, 'foo', (): any => { }).dispose();
assert.equal(lastUnregister, 'foo');
assert.equal(CommandsRegistry.getCommand('foo'), undefined);
@@ -49,7 +49,7 @@ suite('ExtHostCommands', function () {
};
const commands = new ExtHostCommands(SingleProxyRPCProtocol(shape), undefined, new NullLogService());
const reg = commands.registerCommand('foo', (): any => { });
const reg = commands.registerCommand(true, 'foo', (): any => { });
reg.dispose();
reg.dispose();
reg.dispose();

View File

@@ -17,6 +17,7 @@ import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { NullLogService } from 'vs/platform/log/common/log';
import { assign } from 'vs/base/common/objects';
suite('ExtHostConfiguration', function () {
@@ -41,7 +42,8 @@ suite('ExtHostConfiguration', function () {
user: new ConfigurationModel(contents),
workspace: new ConfigurationModel(),
folders: Object.create(null),
configurationScopes: {}
configurationScopes: {},
isComplete: true
};
}
@@ -102,35 +104,164 @@ suite('ExtHostConfiguration', function () {
'config2': 'Das Pferd frisst kein Reis.'
},
'config4': ''
},
'workbench': {
'colorCustomizations': {
'statusBar.foreground': 'somevalue'
}
}
});
let testObject = all.getConfiguration();
let actual = testObject.get('farboo');
actual['nested']['config1'] = 41;
assert.equal(41, actual['nested']['config1']);
actual['farboo1'] = 'newValue';
assert.equal('newValue', actual['farboo1']);
testObject = all.getConfiguration();
testObject['farboo']['farboo1'] = 'newValue';
assert.equal('newValue', testObject['farboo']['farboo1']);
actual = testObject.get('farboo');
assert.equal(actual['nested']['config1'], 42);
assert.equal(actual['farboo1'], undefined);
testObject = all.getConfiguration();
testObject['farboo']['farboo1'] = 'newValue';
assert.equal('newValue', testObject.get('farboo')['farboo1']);
actual = testObject.get('farboo');
assert.equal(actual['config0'], true);
actual['config0'] = false;
assert.equal(actual['config0'], false);
testObject = all.getConfiguration();
actual = testObject.get('farboo');
assert.equal(actual['config0'], true);
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('workbench');
actual = testObject.get('colorCustomizations');
delete actual['statusBar.foreground'];
assert.equal(actual['statusBar.foreground'], undefined);
testObject = all.getConfiguration('workbench');
actual = testObject.get('colorCustomizations');
assert.equal(actual['statusBar.foreground'], 'somevalue');
});
testObject = all.getConfiguration();
testObject['farboo']['farboo1'] = 'newValue';
testObject = all.getConfiguration();
assert.equal(undefined, testObject['farboo']['farboo1']);
test('Stringify returned configuration', function () {
const all = createExtHostConfiguration({
'farboo': {
'config0': true,
'nested': {
'config1': 42,
'config2': 'Das Pferd frisst kein Reis.'
},
'config4': ''
},
'workbench': {
'colorCustomizations': {
'statusBar.foreground': 'somevalue'
},
'emptyobjectkey': {
}
}
});
let testObject = all.getConfiguration();
let actual = testObject.get('farboo');
assert.deepEqual(JSON.stringify({
'config0': true,
'nested': {
'config1': 42,
'config2': 'Das Pferd frisst kein Reis.'
},
'config4': ''
}), JSON.stringify(actual));
assert.deepEqual(undefined, JSON.stringify(testObject.get('unknownkey')));
actual = testObject.get('farboo');
actual['config0'] = false;
assert.deepEqual(JSON.stringify({
'config0': false,
'nested': {
'config1': 42,
'config2': 'Das Pferd frisst kein Reis.'
},
'config4': ''
}), JSON.stringify(actual));
actual = testObject.get('workbench')['colorCustomizations'];
actual['statusBar.background'] = 'anothervalue';
assert.deepEqual(JSON.stringify({
'statusBar.foreground': 'somevalue',
'statusBar.background': 'anothervalue'
}), JSON.stringify(actual));
actual = testObject.get('workbench');
actual['unknownkey'] = 'somevalue';
assert.deepEqual(JSON.stringify({
'colorCustomizations': {
'statusBar.foreground': 'somevalue'
},
'emptyobjectkey': {},
'unknownkey': 'somevalue'
}), JSON.stringify(actual));
actual = all.getConfiguration('workbench').get('emptyobjectkey');
actual = assign(actual || {}, {
'statusBar.background': `#0ff`,
'statusBar.foreground': `#ff0`,
});
assert.deepEqual(JSON.stringify({
'statusBar.background': `#0ff`,
'statusBar.foreground': `#ff0`,
}), JSON.stringify(actual));
actual = all.getConfiguration('workbench').get('unknownkey');
actual = assign(actual || {}, {
'statusBar.background': `#0ff`,
'statusBar.foreground': `#ff0`,
});
assert.deepEqual(JSON.stringify({
'statusBar.background': `#0ff`,
'statusBar.foreground': `#ff0`,
}), JSON.stringify(actual));
});
test('cannot modify returned configuration', function () {
const all = createExtHostConfiguration({
'farboo': {
'config0': true,
'nested': {
'config1': 42,
'config2': 'Das Pferd frisst kein Reis.'
},
'config4': ''
}
});
let testObject = all.getConfiguration();
try {
testObject['get'] = null;
assert.fail('This should be readonly');
} catch (e) {
}
try {
testObject['farboo']['config0'] = false;
assert.fail('This should be readonly');
} catch (e) {
}
try {
testObject['farboo']['farboo1'] = 'hello';
assert.fail('This should be readonly');
} catch (e) {
}
});
test('inspect in no workspace context', function () {
@@ -150,7 +281,8 @@ suite('ExtHostConfiguration', function () {
}, ['editor.wordWrap']),
workspace: new ConfigurationModel({}, []),
folders: Object.create(null),
configurationScopes: {}
configurationScopes: {},
isComplete: true
}
);
@@ -196,7 +328,8 @@ suite('ExtHostConfiguration', function () {
}, ['editor.wordWrap']),
workspace,
folders,
configurationScopes: {}
configurationScopes: {},
isComplete: true
}
);
@@ -270,7 +403,8 @@ suite('ExtHostConfiguration', function () {
}, ['editor.wordWrap']),
workspace,
folders,
configurationScopes: {}
configurationScopes: {},
isComplete: true
}
);

View File

@@ -7,12 +7,12 @@
import * as assert from 'assert';
import URI, { UriComponents } from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import { DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics';
import { Diagnostic, DiagnosticSeverity, Range } from 'vs/workbench/api/node/extHostTypes';
import { Diagnostic, DiagnosticSeverity, Range, DiagnosticRelatedInformation, Location } from 'vs/workbench/api/node/extHostTypes';
import { MainThreadDiagnosticsShape } from 'vs/workbench/api/node/extHost.protocol';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers';
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { Emitter, toPromise } from 'vs/base/common/event';
suite('ExtHostDiagnostics', () => {
@@ -27,7 +27,7 @@ suite('ExtHostDiagnostics', () => {
test('disposeCheck', function () {
const collection = new DiagnosticCollection('test', new DiagnosticsShape());
const collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter());
collection.dispose();
collection.dispose(); // that's OK
@@ -44,13 +44,13 @@ suite('ExtHostDiagnostics', () => {
test('diagnostic collection, forEach, clear, has', function () {
let collection = new DiagnosticCollection('test', new DiagnosticsShape());
let collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter());
assert.equal(collection.name, 'test');
collection.dispose();
assert.throws(() => collection.name);
let c = 0;
collection = new DiagnosticCollection('test', new DiagnosticsShape());
collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter());
collection.forEach(() => c++);
assert.equal(c, 0);
@@ -87,7 +87,7 @@ suite('ExtHostDiagnostics', () => {
});
test('diagnostic collection, immutable read', function () {
let collection = new DiagnosticCollection('test', new DiagnosticsShape());
let collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter());
collection.set(URI.parse('foo:bar'), [
new Diagnostic(new Range(0, 0, 1, 1), 'message-1'),
new Diagnostic(new Range(0, 0, 1, 1), 'message-2')
@@ -112,7 +112,7 @@ suite('ExtHostDiagnostics', () => {
test('diagnostics collection, set with dupliclated tuples', function () {
let collection = new DiagnosticCollection('test', new DiagnosticsShape());
let collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter());
let uri = URI.parse('sc:hightower');
collection.set([
[uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]],
@@ -168,7 +168,7 @@ suite('ExtHostDiagnostics', () => {
lastEntries = entries;
return super.$changeMany(owner, entries);
}
});
}, new Emitter());
let uri = URI.parse('sc:hightower');
collection.set([[uri, [new Diagnostic(new Range(0, 0, 1, 1), 'error')]]]);
@@ -192,7 +192,7 @@ suite('ExtHostDiagnostics', () => {
test('diagnostics collection, tuples and undefined (small array), #15585', function () {
const collection = new DiagnosticCollection('test', new DiagnosticsShape());
const collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter());
let uri = URI.parse('sc:hightower');
let uri2 = URI.parse('sc:nomad');
let diag = new Diagnostic(new Range(0, 0, 0, 1), 'ffff');
@@ -213,7 +213,7 @@ suite('ExtHostDiagnostics', () => {
test('diagnostics collection, tuples and undefined (large array), #15585', function () {
const collection = new DiagnosticCollection('test', new DiagnosticsShape());
const collection = new DiagnosticCollection('test', new DiagnosticsShape(), new Emitter());
const tuples: [URI, Diagnostic[]][] = [];
for (let i = 0; i < 500; i++) {
@@ -242,7 +242,7 @@ suite('ExtHostDiagnostics', () => {
lastEntries = entries;
return super.$changeMany(owner, entries);
}
});
}, new Emitter());
let uri = URI.parse('aa:bb');
let diagnostics: Diagnostic[] = [];
@@ -256,8 +256,72 @@ suite('ExtHostDiagnostics', () => {
assert.equal(collection.get(uri).length, 500);
assert.equal(lastEntries.length, 1);
assert.equal(lastEntries[0][1].length, 251);
assert.equal(lastEntries[0][1][0].severity, Severity.Error);
assert.equal(lastEntries[0][1][200].severity, Severity.Warning);
assert.equal(lastEntries[0][1][250].severity, Severity.Error);
assert.equal(lastEntries[0][1][0].severity, MarkerSeverity.Error);
assert.equal(lastEntries[0][1][200].severity, MarkerSeverity.Warning);
assert.equal(lastEntries[0][1][250].severity, MarkerSeverity.Error);
});
test('diagnostic eventing', async function () {
let emitter = new Emitter<(string | URI)[]>();
let collection = new DiagnosticCollection('ddd', new DiagnosticsShape(), emitter);
let diag1 = new Diagnostic(new Range(1, 1, 2, 3), 'diag1');
let diag2 = new Diagnostic(new Range(1, 1, 2, 3), 'diag2');
let diag3 = new Diagnostic(new Range(1, 1, 2, 3), 'diag3');
let p = toPromise(emitter.event).then(a => {
assert.equal(a.length, 1);
assert.equal(a[0].toString(), 'aa:bb');
assert.ok(URI.isUri(a[0]));
});
collection.set(URI.parse('aa:bb'), []);
await p;
p = toPromise(emitter.event).then(e => {
assert.equal(e.length, 2);
assert.ok(URI.isUri(e[0]));
assert.ok(URI.isUri(e[1]));
assert.equal(e[0].toString(), 'aa:bb');
assert.equal(e[1].toString(), 'aa:cc');
});
collection.set([
[URI.parse('aa:bb'), [diag1]],
[URI.parse('aa:cc'), [diag2, diag3]],
]);
await p;
p = toPromise(emitter.event).then(e => {
assert.equal(e.length, 2);
assert.ok(typeof e[0] === 'string');
assert.ok(typeof e[1] === 'string');
});
collection.clear();
await p;
});
test('diagnostics with related information', function (done) {
let collection = new DiagnosticCollection('ddd', new class extends DiagnosticsShape {
$changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]) {
let [[, data]] = entries;
assert.equal(entries.length, 1);
assert.equal(data.length, 1);
let [diag] = data;
assert.equal(diag.relatedInformation.length, 2);
assert.equal(diag.relatedInformation[0].message, 'more1');
assert.equal(diag.relatedInformation[1].message, 'more2');
done();
}
}, new Emitter<any>());
let diag = new Diagnostic(new Range(0, 0, 1, 1), 'Foo');
diag.relatedInformation = [
new DiagnosticRelatedInformation(new Location(URI.parse('cc:dd'), new Range(0, 0, 0, 0)), 'more1'),
new DiagnosticRelatedInformation(new Location(URI.parse('cc:ee'), new Range(0, 0, 0, 0)), 'more2')
];
collection.set(URI.parse('aa:bb'), [diag]);
});
});

View File

@@ -101,6 +101,7 @@ suite('ExtHostDocumentData', () => {
data.onEvents({
changes: [{
range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 },
rangeOffset: undefined,
rangeLength: undefined,
text: '\t '
}],
@@ -157,6 +158,7 @@ suite('ExtHostDocumentData', () => {
data.onEvents({
changes: [{
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
rangeOffset: undefined,
rangeLength: undefined,
text: ''
}],
@@ -174,6 +176,7 @@ suite('ExtHostDocumentData', () => {
data.onEvents({
changes: [{
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
rangeOffset: undefined,
rangeLength: undefined,
text: 'is could be'
}],
@@ -191,6 +194,7 @@ suite('ExtHostDocumentData', () => {
data.onEvents({
changes: [{
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
rangeOffset: undefined,
rangeLength: undefined,
text: 'is could be\na line with number'
}],
@@ -211,6 +215,7 @@ suite('ExtHostDocumentData', () => {
data.onEvents({
changes: [{
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 2, endColumn: 6 },
rangeOffset: undefined,
rangeLength: undefined,
text: ''
}],
@@ -344,6 +349,7 @@ suite('ExtHostDocumentData updates line mapping', () => {
return {
changes: [{
range: range,
rangeOffset: undefined,
rangeLength: undefined,
text: text
}],

View File

@@ -19,6 +19,7 @@ import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { NullLogService } from 'vs/platform/log/common/log';
import { isResourceTextEdit, ResourceTextEdit } from 'vs/editor/common/modes';
import { timeout } from 'vs/base/common/async';
suite('ExtHostDocumentSaveParticipant', () => {
@@ -166,12 +167,12 @@ suite('ExtHostDocumentSaveParticipant', () => {
let callCount = 0;
let sub1 = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) {
callCount += 1;
event.waitUntil(TPromise.timeout(17));
event.waitUntil(timeout(17));
});
let sub2 = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) {
callCount += 1;
event.waitUntil(TPromise.timeout(17));
event.waitUntil(timeout(17));
});
let sub3 = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) {
@@ -193,9 +194,9 @@ suite('ExtHostDocumentSaveParticipant', () => {
let sub = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) {
event.waitUntil(TPromise.timeout(10));
event.waitUntil(TPromise.timeout(10));
event.waitUntil(TPromise.timeout(10));
event.waitUntil(timeout(10));
event.waitUntil(timeout(10));
event.waitUntil(timeout(10));
});
return participant.$participateInSave(resource, SaveReason.EXPLICIT).then(() => {
@@ -212,7 +213,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
event.waitUntil(new TPromise((resolve, reject) => {
setTimeout(() => {
try {
assert.throws(() => event.waitUntil(TPromise.timeout(10)));
assert.throws(() => event.waitUntil(timeout(10)));
resolve(void 0);
} catch (e) {
reject(e);
@@ -231,7 +232,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
const participant = new ExtHostDocumentSaveParticipant(nullLogService, documents, mainThreadEditors, { timeout: 5, errors: 3 });
let sub = participant.getOnWillSaveTextDocumentEvent(nullExtensionDescription)(function (event) {
event.waitUntil(TPromise.timeout(15));
event.waitUntil(timeout(15));
});
return participant.$participateInSave(resource, SaveReason.EXPLICIT).then(values => {
@@ -301,6 +302,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
documents.$acceptModelChanged(resource, {
changes: [{
range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 },
rangeOffset: undefined,
rangeLength: undefined,
text: 'bar'
}],
@@ -336,6 +338,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
changes: [{
range,
text,
rangeOffset: undefined,
rangeLength: undefined,
}],
eol: undefined,

View File

@@ -30,7 +30,7 @@ import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefiniti
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 { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
import { getWorkspaceSymbols } from 'vs/workbench/parts/search/common/search';
import { rename } from 'vs/editor/contrib/rename/rename';
import { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
@@ -45,6 +45,7 @@ import * as vscode from 'vscode';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { NullLogService } from 'vs/platform/log/common/log';
import { ITextModel, EndOfLineSequence } from 'vs/editor/common/model';
import { getColors } from 'vs/editor/contrib/colorPicker/color';
const defaultSelector = { scheme: 'far' };
const model: ITextModel = EditorModel.createFromString(
@@ -110,7 +111,7 @@ suite('ExtHostLanguageFeatures', function () {
const diagnostics = new ExtHostDiagnostics(rpcProtocol);
rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
extHost = new ExtHostLanguageFeatures(rpcProtocol, extHostDocuments, commands, heapService, diagnostics);
extHost = new ExtHostLanguageFeatures(rpcProtocol, null, extHostDocuments, commands, heapService, diagnostics);
rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost);
mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, inst.createInstance(MainThreadLanguageFeatures, rpcProtocol));
@@ -1033,6 +1034,13 @@ suite('ExtHostLanguageFeatures', function () {
});
test('Format Doc, order', function () {
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, <vscode.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits(): any {
return undefined;
}
}));
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, <vscode.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')];
@@ -1078,6 +1086,11 @@ suite('ExtHostLanguageFeatures', function () {
return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'range')];
}
}));
disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultSelector, <vscode.DocumentRangeFormattingEditProvider>{
provideDocumentRangeFormattingEdits(): any {
return [new types.TextEdit(new types.Range(2, 3, 4, 5), 'range2')];
}
}));
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, <vscode.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'doc')];
@@ -1087,7 +1100,11 @@ suite('ExtHostLanguageFeatures', function () {
return getDocumentRangeFormattingEdits(model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }).then(value => {
assert.equal(value.length, 1);
let [first] = value;
assert.equal(first.text, 'range');
assert.equal(first.text, 'range2');
assert.equal(first.range.startLineNumber, 3);
assert.equal(first.range.startColumn, 4);
assert.equal(first.range.endLineNumber, 5);
assert.equal(first.range.endColumn, 6);
});
});
});
@@ -1166,4 +1183,26 @@ suite('ExtHostLanguageFeatures', function () {
});
});
});
test('Document colors, data conversion', function () {
disposables.push(extHost.registerColorProvider(defaultSelector, <vscode.DocumentColorProvider>{
provideDocumentColors(): vscode.ColorInformation[] {
return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))];
},
provideColorPresentations(color: vscode.Color, context: { range: vscode.Range, document: vscode.TextDocument }): vscode.ColorPresentation[] {
return [];
}
}));
return rpcProtocol.sync().then(() => {
return getColors(model).then(value => {
assert.equal(value.length, 1);
let [first] = value;
assert.deepEqual(first.colorInfo.color, { red: 0.1, green: 0.2, blue: 0.3, alpha: 0.4 });
assert.deepEqual(first.colorInfo.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 21 });
});
});
});
});

View File

@@ -8,13 +8,17 @@
import * as assert from 'assert';
import { MainThreadMessageService } from 'vs/workbench/api/electron-browser/mainThreadMessageService';
import { TPromise as Promise, TPromise } from 'vs/base/common/winjs.base';
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, INotification, NoOpNotification, INotificationHandle, IPromptChoice, Severity } from 'vs/platform/notification/common/notification';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice } from 'vs/platform/notification/common/notification';
import { ICommandService } from 'vs/platform/commands/common/commands';
const emptyChoiceService = new class implements IChoiceService {
_serviceBrand: 'choiceService';
choose(severity, message, options, modal): never {
const emptyDialogService = new class implements IDialogService {
_serviceBrand: 'dialogService';
show(severity, message, buttons): never {
throw new Error('not implemented');
}
confirm(...opts): never {
throw new Error('not implemented');
}
};
@@ -79,7 +83,7 @@ suite('ExtHostMessageService', function () {
let service = new MainThreadMessageService(null, new EmptyNotificationService(notification => {
assert.equal(notification.actions.primary.length, 1);
setImmediate(() => notification.actions.primary[0].run());
}), emptyCommandService, emptyChoiceService, null);
}), emptyCommandService, emptyDialogService, null);
return service.$showMessage(1, 'h', {}, [{ handle: 42, title: 'a thing', isCloseAffordance: true }]).then(handle => {
assert.equal(handle, 42);
@@ -87,16 +91,16 @@ suite('ExtHostMessageService', function () {
});
suite('modal', () => {
test('calls choice service', () => {
test('calls dialog service', () => {
const service = new MainThreadMessageService(null, emptyNotificationService, emptyCommandService, {
choose(severity, message, options, modal) {
show(severity, message, buttons) {
assert.equal(severity, 1);
assert.equal(message, 'h');
assert.equal(options.length, 2);
assert.equal(options[1], 'Cancel');
assert.equal(buttons.length, 2);
assert.equal(buttons[1], 'Cancel');
return Promise.as(0);
}
} as IChoiceService, null);
} as IDialogService, null);
return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: false }]).then(handle => {
assert.equal(handle, 42);
@@ -105,10 +109,10 @@ suite('ExtHostMessageService', function () {
test('returns undefined when cancelled', () => {
const service = new MainThreadMessageService(null, emptyNotificationService, emptyCommandService, {
choose(severity, message, options, modal) {
show(severity, message, buttons) {
return Promise.as(1);
}
} as IChoiceService, null);
} as IDialogService, null);
return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: false }]).then(handle => {
assert.equal(handle, undefined);
@@ -117,11 +121,11 @@ suite('ExtHostMessageService', function () {
test('hides Cancel button when not needed', () => {
const service = new MainThreadMessageService(null, emptyNotificationService, emptyCommandService, {
choose(severity, message, options, modal) {
assert.equal(options.length, 1);
show(severity, message, buttons) {
assert.equal(buttons.length, 1);
return Promise.as(0);
}
} as IChoiceService, null);
} as IDialogService, null);
return service.$showMessage(1, 'h', { modal: true }, [{ handle: 42, title: 'a thing', isCloseAffordance: true }]).then(handle => {
assert.equal(handle, 42);

View File

@@ -75,8 +75,8 @@ suite('ExtHostTreeView', function () {
testObject = new ExtHostTreeViews(target, new ExtHostCommands(rpcProtocol, new ExtHostHeapService(), new NullLogService()));
onDidChangeTreeNode = new Emitter<{ key: string }>();
onDidChangeTreeNodeWithId = new Emitter<{ key: string }>();
testObject.registerTreeDataProvider('testNodeTreeProvider', aNodeTreeDataProvider(), (fn) => fn);
testObject.registerTreeDataProvider('testNodeWithIdTreeProvider', aNodeWithIdTreeDataProvider(), (fn) => fn);
testObject.createTreeView('testNodeTreeProvider', { treeDataProvider: aNodeTreeDataProvider() });
testObject.createTreeView('testNodeWithIdTreeProvider', { treeDataProvider: aNodeWithIdTreeDataProvider() });
testObject.$getChildren('testNodeTreeProvider').then(elements => {
for (const element of elements) {
@@ -405,14 +405,14 @@ suite('ExtHostTreeView', function () {
});
test('reveal will throw an error if getParent is not implemented', () => {
const treeView = testObject.registerTreeDataProvider('treeDataProvider', aNodeTreeDataProvider(), (fn) => fn);
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aNodeTreeDataProvider() });
return treeView.reveal({ key: 'a' })
.then(() => assert.fail('Reveal should throw an error as getParent is not implemented'), () => null);
});
test('reveal will return empty array for root element', () => {
const revealTarget = sinon.spy(target, '$reveal');
const treeView = testObject.registerTreeDataProvider('treeDataProvider', aCompleteNodeTreeDataProvider(), (fn) => fn);
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() });
return treeView.reveal({ key: 'a' })
.then(() => {
assert.ok(revealTarget.calledOnce);
@@ -423,9 +423,9 @@ suite('ExtHostTreeView', function () {
});
});
test('reveal will return parents array for an element', () => {
test('reveal will return parents array for an element when hierarchy is not loaded', () => {
const revealTarget = sinon.spy(target, '$reveal');
const treeView = testObject.registerTreeDataProvider('treeDataProvider', aCompleteNodeTreeDataProvider(), (fn) => fn);
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() });
return treeView.reveal({ key: 'aa' })
.then(() => {
assert.ok(revealTarget.calledOnce);
@@ -436,6 +436,21 @@ suite('ExtHostTreeView', function () {
});
});
test('reveal will return parents array for an element when hierarchy is loaded', () => {
const revealTarget = sinon.spy(target, '$reveal');
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() });
return testObject.$getChildren('treeDataProvider')
.then(() => testObject.$getChildren('treeDataProvider', '0/0:a'))
.then(() => treeView.reveal({ key: 'aa' })
.then(() => {
assert.ok(revealTarget.calledOnce);
assert.deepEqual('treeDataProvider', revealTarget.args[0][0]);
assert.deepEqual({ handle: '0/0:a/0:aa', label: 'aa', collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:a' }, removeUnsetKeys(revealTarget.args[0][1]));
assert.deepEqual([{ handle: '0/0:a', label: 'a', collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][2]).map(arg => removeUnsetKeys(arg)));
assert.equal(void 0, revealTarget.args[0][3]);
}));
});
test('reveal will return parents array for deeper element with no selection', () => {
tree = {
'b': {
@@ -445,7 +460,7 @@ suite('ExtHostTreeView', function () {
}
};
const revealTarget = sinon.spy(target, '$reveal');
const treeView = testObject.registerTreeDataProvider('treeDataProvider', aCompleteNodeTreeDataProvider(), (fn) => fn);
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() });
return treeView.reveal({ key: 'bac' }, { select: false })
.then(() => {
assert.ok(revealTarget.calledOnce);

View File

@@ -513,4 +513,10 @@ suite('ExtHostTypes', function () {
assert.equal(string.value, '${BAR}');
});
test('instanceof doesn\'t work for FileSystemError #49386', function () {
const error = types.FileSystemError.Unavailable('foo');
assert.ok(error instanceof Error);
assert.ok(error instanceof types.FileSystemError);
});
});

View File

@@ -0,0 +1,62 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { MainThreadWebviews } from 'vs/workbench/api/electron-browser/mainThreadWebview';
import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview';
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import * as vscode from 'vscode';
import { SingleProxyRPCProtocol } from './testRPCProtocol';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
suite('ExtHostWebview', function () {
test('Cannot register multiple serializer for the same view type', async () => {
const viewType = 'view.type';
const shape = createNoopMainThreadWebviews();
const extHostWebviews = new ExtHostWebviews(SingleProxyRPCProtocol(shape));
let lastInvokedDeserializer: vscode.WebviewPanelSerializer | undefined = undefined;
class NoopSerializer implements vscode.WebviewPanelSerializer {
async serializeWebviewPanel(webview: vscode.WebviewPanel): Promise<any> { /* noop */ }
async deserializeWebviewPanel(webview: vscode.WebviewPanel, state: any): Promise<void> {
lastInvokedDeserializer = this;
}
}
const serializerA = new NoopSerializer();
const serializerB = new NoopSerializer();
const serializerARegistration = extHostWebviews.registerWebviewPanelSerializer(viewType, serializerA);
await extHostWebviews.$deserializeWebviewPanel('x', viewType, 'title', {}, EditorPosition.ONE, {});
assert.strictEqual(lastInvokedDeserializer, serializerA);
assert.throws(
() => extHostWebviews.registerWebviewPanelSerializer(viewType, serializerB),
'Should throw when registering two serializers for the same view');
serializerARegistration.dispose();
extHostWebviews.registerWebviewPanelSerializer(viewType, serializerB);
await extHostWebviews.$deserializeWebviewPanel('x', viewType, 'title', {}, EditorPosition.ONE, {});
assert.strictEqual(lastInvokedDeserializer, serializerB);
});
});
function createNoopMainThreadWebviews() {
return new class extends mock<MainThreadWebviews>() {
$registerSerializer() { /* noop */ }
$unregisterSerializer() { /* noop */ }
};
}

View File

@@ -8,7 +8,7 @@
import * as assert from 'assert';
import { BoundModelReferenceCollection } from 'vs/workbench/api/electron-browser/mainThreadDocuments';
import { TextModel } from 'vs/editor/common/model/textModel';
import { TPromise } from 'vs/base/common/winjs.base';
import { timeout } from 'vs/base/common/async';
suite('BoundModelReferenceCollection', () => {
@@ -29,7 +29,7 @@ suite('BoundModelReferenceCollection', () => {
}
});
return TPromise.timeout(30).then(() => {
return timeout(30).then(() => {
assert.equal(didDispose, true);
});
});

View File

@@ -17,7 +17,7 @@ import { ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta } from 'vs/w
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';
import { Event } from 'vs/base/common/event';
suite('MainThreadDocumentsAndEditors', () => {
@@ -89,7 +89,22 @@ suite('MainThreadDocumentsAndEditors', () => {
this.timeout(1000 * 60); // increase timeout for this one test
const model = modelService.createModel(hugeModelString, null, null);
assert.ok(model.isTooLargeForHavingARichMode());
assert.ok(model.isTooLargeForSyncing());
assert.equal(deltas.length, 1);
const [delta] = deltas;
assert.equal(delta.newActiveEditor, null);
assert.equal(delta.addedDocuments, undefined);
assert.equal(delta.removedDocuments, undefined);
assert.equal(delta.addedEditors, undefined);
assert.equal(delta.removedEditors, undefined);
});
test('ignore simple widget model', function () {
this.timeout(1000 * 60); // increase timeout for this one test
const model = modelService.createModel('test', null, null, true);
assert.ok(model.isForSimpleWidget);
assert.equal(deltas.length, 1);
const [delta] = deltas;

View File

@@ -16,7 +16,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi
import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape } from 'vs/workbench/api/node/extHost.protocol';
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';
import { Event } from 'vs/base/common/event';
import { MainThreadTextEditors } from 'vs/workbench/api/electron-browser/mainThreadEditors';
import URI from 'vs/base/common/uri';
import { Range } from 'vs/editor/common/core/range';

View File

@@ -20,7 +20,7 @@ import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/commo
import { snapshotToString } from 'vs/platform/files/common/files';
class ServiceAccessor {
constructor( @ITextFileService public textFileService: TestTextFileService, @IModelService public modelService: IModelService) {
constructor(@ITextFileService public textFileService: TestTextFileService, @IModelService public modelService: IModelService) {
}
}
@@ -39,10 +39,10 @@ suite('MainThreadSaveParticipant', function () {
TextFileEditorModel.setSaveParticipant(null); // reset any set participant
});
test('insert final new line', function (done) {
test('insert final new line', function () {
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/final_new_line.txt'), 'utf8');
model.load().then(() => {
return model.load().then(() => {
const configService = new TestConfigurationService();
configService.setUserConfiguration('files', { 'insertFinalNewline': true });
@@ -71,15 +71,13 @@ suite('MainThreadSaveParticipant', function () {
model.textEditorModel.setValue(lineContent);
participant.participate(model, { reason: SaveReason.EXPLICIT });
assert.equal(snapshotToString(model.createSnapshot()), `${lineContent}${model.textEditorModel.getEOL()}`);
done();
});
});
test('trim final new lines', function (done) {
test('trim final new lines', function () {
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8');
model.load().then(() => {
return model.load().then(() => {
const configService = new TestConfigurationService();
configService.setUserConfiguration('files', { 'trimFinalNewlines': true });
@@ -111,15 +109,13 @@ suite('MainThreadSaveParticipant', function () {
model.textEditorModel.setValue(lineContent);
participant.participate(model, { reason: SaveReason.EXPLICIT });
assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}${textContent}${eol}`);
done();
});
});
test('trim final new lines bug#39750', function (done) {
test('trim final new lines bug#39750', function () {
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8');
model.load().then(() => {
return model.load().then(() => {
const configService = new TestConfigurationService();
configService.setUserConfiguration('files', { 'trimFinalNewlines': true });
@@ -140,8 +136,34 @@ suite('MainThreadSaveParticipant', function () {
participant.participate(model, { reason: SaveReason.EXPLICIT });
model.textEditorModel.redo();
assert.equal(snapshotToString(model.createSnapshot()), `${textContent}.`);
done();
});
});
test('trim final new lines bug#46075', function () {
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/trim_final_new_line.txt'), 'utf8');
return model.load().then(() => {
const configService = new TestConfigurationService();
configService.setUserConfiguration('files', { 'trimFinalNewlines': true });
const participant = new TrimFinalNewLinesParticipant(configService, undefined);
const textContent = 'Test';
const eol = `${model.textEditorModel.getEOL()}`;
let content = `${textContent}${eol}${eol}`;
model.textEditorModel.setValue(content);
// save many times
for (let i = 0; i < 10; i++) {
participant.participate(model, { reason: SaveReason.EXPLICIT });
}
// confirm trimming
assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}`);
// undo should go back to previous content immediately
model.textEditorModel.undo();
assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}${eol}`);
model.textEditorModel.redo();
assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}`);
});
});
});

View File

@@ -32,9 +32,9 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { SearchModel } from 'vs/workbench/parts/search/common/searchModel';
import { QueryBuilder } from 'vs/workbench/parts/search/common/queryBuilder';
import Event, * as event from 'vs/base/common/event';
import * as event from 'vs/base/common/event';
import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
import { ILogService, NullLogService } from '../../../platform/log/common/log';
import { NullLogService, ILogService } from 'vs/platform/log/common/log';
declare var __dirname: string;
@@ -150,7 +150,7 @@ class TestTelemetryService implements ITelemetryService {
private emitter = new event.Emitter<any>();
public get eventLogged(): Event<any> {
public get eventLogged(): event.Event<any> {
return this.emitter.event;
}