extHostLanguageFeatures.test.ts 43.3 KB
Newer Older
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as assert from 'assert';
7
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
J
Johannes Rieken 已提交
8
import { setUnexpectedErrorHandler, errorHandler } from 'vs/base/common/errors';
9
import { URI } from 'vs/base/common/uri';
J
Johannes Rieken 已提交
10
import * as types from 'vs/workbench/api/node/extHostTypes';
A
Alex Dima 已提交
11
import { TextModel as EditorModel } from 'vs/editor/common/model/textModel';
12
import { Position as EditorPosition, Position } from 'vs/editor/common/core/position';
J
Johannes Rieken 已提交
13
import { Range as EditorRange } from 'vs/editor/common/core/range';
A
Alex Dima 已提交
14
import { TestRPCProtocol } from './testRPCProtocol';
J
Johannes Rieken 已提交
15
import { IMarkerService } from 'vs/platform/markers/common/markers';
16
import { MarkerService } from 'vs/platform/markers/common/markerService';
J
Johannes Rieken 已提交
17
import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures';
18
import { MainThreadLanguageFeatures } from 'vs/workbench/api/electron-browser/mainThreadLanguageFeatures';
J
Johannes Rieken 已提交
19
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
20 21
import { MainThreadCommands } from 'vs/workbench/api/electron-browser/mainThreadCommands';
import { IHeapService } from 'vs/workbench/api/electron-browser/mainThreadHeapService';
J
Johannes Rieken 已提交
22
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
J
Johannes Rieken 已提交
23
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
24
import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen';
25
import * as modes from 'vs/editor/common/modes';
26
import { getCodeLensData } from 'vs/editor/contrib/codelens/codelens';
27
import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition, getDeclarationsAtPosition } from 'vs/editor/contrib/goToDefinition/goToDefinition';
28 29 30
import { getHover } from 'vs/editor/contrib/hover/getHover';
import { getOccurrencesAtPosition } from 'vs/editor/contrib/wordHighlighter/wordHighlighter';
import { provideReferences } from 'vs/editor/contrib/referenceSearch/referenceSearch';
31
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
32
import { getWorkspaceSymbols } from 'vs/workbench/contrib/search/common/search';
33 34 35
import { rename } from 'vs/editor/contrib/rename/rename';
import { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
import { provideSuggestionItems } from 'vs/editor/contrib/suggest/suggest';
36
import { getDocumentFormattingEdits, getDocumentRangeFormattingEdits, getOnTypeFormattingEdits, FormatMode } from 'vs/editor/contrib/format/format';
37
import { getLinks } from 'vs/editor/contrib/links/getLinks';
J
Johannes Rieken 已提交
38 39 40
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';
41
import * as vscode from 'vscode';
B
Benjamin Pasero 已提交
42
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
43
import { NullLogService } from 'vs/platform/log/common/log';
A
Alex Dima 已提交
44
import { ITextModel, EndOfLineSequence } from 'vs/editor/common/model';
45
import { getColors } from 'vs/editor/contrib/colorPicker/color';
46
import { CancellationToken } from 'vs/base/common/cancellation';
47
import { nullExtensionDescription as defaultExtension } from 'vs/workbench/services/extensions/common/extensions';
48
import { provideSelectionRanges } from 'vs/editor/contrib/smartSelect/smartSelect';
J
Johannes Rieken 已提交
49 50 51
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
52 53

const defaultSelector = { scheme: 'far' };
A
Alex Dima 已提交
54
const model: ITextModel = EditorModel.createFromString(
55 56 57 58 59
	[
		'This is the first line',
		'This is the second line',
		'This is the third line',
	].join('\n'),
60
	undefined,
61
	undefined,
J
Johannes Rieken 已提交
62
	URI.parse('far://testing/file.a'));
63 64 65 66

let extHost: ExtHostLanguageFeatures;
let mainThread: MainThreadLanguageFeatures;
let disposables: vscode.Disposable[] = [];
A
Alex Dima 已提交
67
let rpcProtocol: TestRPCProtocol;
68 69
let originalErrorHandler: (e: any) => any;

J
Johannes Rieken 已提交
70 71


J
Johannes Rieken 已提交
72
suite('ExtHostLanguageFeatures', function () {
73 74 75

	suiteSetup(() => {

A
Alex Dima 已提交
76
		rpcProtocol = new TestRPCProtocol();
77 78 79 80 81 82 83 84

		// Use IInstantiationService to get typechecking when instantiating
		let inst: IInstantiationService;
		{
			let instantiationService = new TestInstantiationService();
			instantiationService.stub(IMarkerService, MarkerService);
			instantiationService.stub(IHeapService, {
				_serviceBrand: undefined,
J
Johannes Rieken 已提交
85
				trackObject(_obj: any) {
86 87 88 89 90
					// nothing
				}
			});
			inst = instantiationService;
		}
J
Johannes Rieken 已提交
91

92 93 94
		originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
		setUnexpectedErrorHandler(() => { });

A
Alex Dima 已提交
95
		const extHostDocumentsAndEditors = new ExtHostDocumentsAndEditors(rpcProtocol);
J
Johannes Rieken 已提交
96 97 98 99 100
		extHostDocumentsAndEditors.$acceptDocumentsAndEditorsDelta({
			addedDocuments: [{
				isDirty: false,
				versionId: model.getVersionId(),
				modeId: model.getLanguageIdentifier().language,
101
				uri: model.uri,
J
Johannes Rieken 已提交
102 103 104
				lines: model.getValue().split(model.getEOL()),
				EOL: model.getEOL(),
			}]
105
		});
A
Alex Dima 已提交
106 107
		const extHostDocuments = new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors);
		rpcProtocol.set(ExtHostContext.ExtHostDocuments, extHostDocuments);
108

109 110
		const heapService = new ExtHostHeapService();

A
Alex Dima 已提交
111 112 113
		const commands = new ExtHostCommands(rpcProtocol, heapService, new NullLogService());
		rpcProtocol.set(ExtHostContext.ExtHostCommands, commands);
		rpcProtocol.set(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, rpcProtocol));
114

A
Alex Dima 已提交
115 116
		const diagnostics = new ExtHostDiagnostics(rpcProtocol);
		rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
117

118
		extHost = new ExtHostLanguageFeatures(rpcProtocol, null, extHostDocuments, commands, heapService, diagnostics, new NullLogService());
A
Alex Dima 已提交
119
		rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost);
120

A
Alex Dima 已提交
121
		mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, inst.createInstance(MainThreadLanguageFeatures, rpcProtocol));
122 123 124 125
	});

	suiteTeardown(() => {
		setUnexpectedErrorHandler(originalErrorHandler);
126
		model.dispose();
J
Johannes Rieken 已提交
127
		mainThread.dispose();
128 129
	});

J
Johannes Rieken 已提交
130
	teardown(function () {
131 132 133
		while (disposables.length) {
			disposables.pop().dispose();
		}
A
Alex Dima 已提交
134
		return rpcProtocol.sync();
135 136
	});

137 138
	// --- outline

M
Matt Bierner 已提交
139
	test('DocumentSymbols, register/deregister', async () => {
140
		assert.equal(modes.DocumentSymbolProviderRegistry.all(model).length, 0);
M
Matt Bierner 已提交
141
		let d1 = extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
142
			provideDocumentSymbols() {
A
Alex Dima 已提交
143
				return <vscode.SymbolInformation[]>[];
144 145 146
			}
		});

M
Matt Bierner 已提交
147 148 149 150
		await rpcProtocol.sync();
		assert.equal(modes.DocumentSymbolProviderRegistry.all(model).length, 1);
		d1.dispose();
		return rpcProtocol.sync();
151 152 153

	});

M
Matt Bierner 已提交
154
	test('DocumentSymbols, evil provider', async () => {
M
Matt Bierner 已提交
155
		disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
156 157 158 159
			provideDocumentSymbols(): any {
				throw new Error('evil document symbol provider');
			}
		}));
M
Matt Bierner 已提交
160
		disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
161
			provideDocumentSymbols(): any {
162
				return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))];
163 164 165
			}
		}));

M
Matt Bierner 已提交
166 167 168
		await rpcProtocol.sync();
		const value = await getDocumentSymbols(model, true, CancellationToken.None);
		assert.equal(value.length, 1);
169 170
	});

M
Matt Bierner 已提交
171
	test('DocumentSymbols, data conversion', async () => {
M
Matt Bierner 已提交
172
		disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
173
			provideDocumentSymbols(): any {
174
				return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))];
175 176 177
			}
		}));

M
Matt Bierner 已提交
178 179 180 181 182 183
		await rpcProtocol.sync();
		const value = await getDocumentSymbols(model, true, CancellationToken.None);
		assert.equal(value.length, 1);
		let entry = value[0];
		assert.equal(entry.name, 'test');
		assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
184
	});
185 186 187

	// --- code lens

M
Matt Bierner 已提交
188
	test('CodeLens, evil provider', async () => {
189

M
Matt Bierner 已提交
190
		disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
J
tslint  
Johannes Rieken 已提交
191
			provideCodeLenses(): any {
B
Benjamin Pasero 已提交
192
				throw new Error('evil');
193 194
			}
		}));
M
Matt Bierner 已提交
195
		disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
196 197 198 199 200
			provideCodeLenses() {
				return [new types.CodeLens(new types.Range(0, 0, 0, 0))];
			}
		}));

M
Matt Bierner 已提交
201 202 203
		await rpcProtocol.sync();
		const value = await getCodeLensData(model, CancellationToken.None);
		assert.equal(value.length, 1);
204 205
	});

M
Matt Bierner 已提交
206
	test('CodeLens, do not resolve a resolved lens', async () => {
207

M
Matt Bierner 已提交
208
		disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
J
tslint  
Johannes Rieken 已提交
209
			provideCodeLenses(): any {
210 211 212
				return [new types.CodeLens(
					new types.Range(0, 0, 0, 0),
					{ command: 'id', title: 'Title' })];
M
Matt Bierner 已提交
213
			}
J
tslint  
Johannes Rieken 已提交
214
			resolveCodeLens(): any {
215 216 217 218
				assert.ok(false, 'do not resolve');
			}
		}));

M
Matt Bierner 已提交
219 220 221 222 223 224 225
		await rpcProtocol.sync();
		const value = await getCodeLensData(model, CancellationToken.None);
		assert.equal(value.length, 1);
		let data = value[0];
		const symbol = await Promise.resolve(data.provider.resolveCodeLens(model, data.symbol, CancellationToken.None));
		assert.equal(symbol.command.id, 'id');
		assert.equal(symbol.command.title, 'Title');
226 227
	});

M
Matt Bierner 已提交
228
	test('CodeLens, missing command', async () => {
229

M
Matt Bierner 已提交
230
		disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
231 232 233 234 235
			provideCodeLenses() {
				return [new types.CodeLens(new types.Range(0, 0, 0, 0))];
			}
		}));

M
Matt Bierner 已提交
236 237 238 239 240 241 242
		await rpcProtocol.sync();
		const value = await getCodeLensData(model, CancellationToken.None);
		assert.equal(value.length, 1);
		let data = value[0];
		const symbol = await Promise.resolve(data.provider.resolveCodeLens(model, data.symbol, CancellationToken.None));
		assert.equal(symbol.command.id, 'missing');
		assert.equal(symbol.command.title, '!!MISSING: command!!');
243
	});
J
Johannes Rieken 已提交
244 245 246

	// --- definition

M
Matt Bierner 已提交
247
	test('Definition, data conversion', async () => {
J
Johannes Rieken 已提交
248

M
Matt Bierner 已提交
249
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
250
			provideDefinition(): any {
251
				return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
J
Johannes Rieken 已提交
252 253 254
			}
		}));

M
Matt Bierner 已提交
255 256 257 258 259 260
		await rpcProtocol.sync();
		let value = await getDefinitionsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 1);
		let [entry] = value;
		assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 });
		assert.equal(entry.uri.toString(), model.uri.toString());
J
Johannes Rieken 已提交
261 262
	});

M
Matt Bierner 已提交
263
	test('Definition, one or many', async () => {
J
Johannes Rieken 已提交
264

M
Matt Bierner 已提交
265
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
266
			provideDefinition(): any {
267
				return [new types.Location(model.uri, new types.Range(1, 1, 1, 1))];
J
Johannes Rieken 已提交
268 269
			}
		}));
M
Matt Bierner 已提交
270
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
271
			provideDefinition(): any {
272
				return new types.Location(model.uri, new types.Range(1, 1, 1, 1));
J
Johannes Rieken 已提交
273 274 275
			}
		}));

M
Matt Bierner 已提交
276 277 278
		await rpcProtocol.sync();
		const value = await getDefinitionsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 2);
J
Johannes Rieken 已提交
279 280
	});

M
Matt Bierner 已提交
281
	test('Definition, registration order', async () => {
J
Johannes Rieken 已提交
282

M
Matt Bierner 已提交
283
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
284 285 286 287 288
			provideDefinition(): any {
				return [new types.Location(URI.parse('far://first'), new types.Range(2, 3, 4, 5))];
			}
		}));

M
Matt Bierner 已提交
289
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
290 291 292 293
			provideDefinition(): any {
				return new types.Location(URI.parse('far://second'), new types.Range(1, 2, 3, 4));
			}
		}));
J
Johannes Rieken 已提交
294

M
Matt Bierner 已提交
295 296 297 298 299 300
		await rpcProtocol.sync();
		const value = await getDefinitionsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 2);
		// let [first, second] = value;
		assert.equal(value[0].uri.authority, 'second');
		assert.equal(value[1].uri.authority, 'first');
J
Johannes Rieken 已提交
301 302
	});

M
Matt Bierner 已提交
303
	test('Definition, evil provider', async () => {
J
Johannes Rieken 已提交
304

M
Matt Bierner 已提交
305
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
306
			provideDefinition(): any {
B
Benjamin Pasero 已提交
307
				throw new Error('evil provider');
J
Johannes Rieken 已提交
308 309
			}
		}));
M
Matt Bierner 已提交
310
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
311
			provideDefinition(): any {
312
				return new types.Location(model.uri, new types.Range(1, 1, 1, 1));
J
Johannes Rieken 已提交
313 314 315
			}
		}));

M
Matt Bierner 已提交
316 317 318
		await rpcProtocol.sync();
		const value = await getDefinitionsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 1);
J
Johannes Rieken 已提交
319
	});
J
Johannes Rieken 已提交
320

321 322
	// -- declaration

M
Matt Bierner 已提交
323
	test('Declaration, data conversion', async () => {
324

M
Matt Bierner 已提交
325
		disposables.push(extHost.registerDeclarationProvider(defaultExtension, defaultSelector, new class implements vscode.DeclarationProvider {
326 327 328 329 330
			provideDeclaration(): any {
				return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
			}
		}));

M
Matt Bierner 已提交
331 332 333 334 335 336
		await rpcProtocol.sync();
		let value = await getDeclarationsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 1);
		let [entry] = value;
		assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 });
		assert.equal(entry.uri.toString(), model.uri.toString());
337 338
	});

339
	// --- implementation
340

M
Matt Bierner 已提交
341
	test('Implementation, data conversion', async () => {
342

M
Matt Bierner 已提交
343
		disposables.push(extHost.registerImplementationProvider(defaultExtension, defaultSelector, new class implements vscode.ImplementationProvider {
M
Matt Bierner 已提交
344
			provideImplementation(): any {
345 346 347 348
				return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
			}
		}));

M
Matt Bierner 已提交
349 350 351 352 353 354
		await rpcProtocol.sync();
		let value = await getImplementationsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 1);
		let [entry] = value;
		assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 });
		assert.equal(entry.uri.toString(), model.uri.toString());
355 356 357 358
	});

	// --- type definition

M
Matt Bierner 已提交
359
	test('Type Definition, data conversion', async () => {
360

M
Matt Bierner 已提交
361
		disposables.push(extHost.registerTypeDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.TypeDefinitionProvider {
362 363 364 365 366
			provideTypeDefinition(): any {
				return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
			}
		}));

M
Matt Bierner 已提交
367 368 369 370 371 372
		await rpcProtocol.sync();
		let value = await getTypeDefinitionsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 1);
		let [entry] = value;
		assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 });
		assert.equal(entry.uri.toString(), model.uri.toString());
373 374
	});

J
Johannes Rieken 已提交
375 376
	// --- extra info

M
Matt Bierner 已提交
377
	test('HoverProvider, word range at pos', async () => {
J
Johannes Rieken 已提交
378

M
Matt Bierner 已提交
379
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
380
			provideHover(): any {
B
Benjamin Pasero 已提交
381
				return new types.Hover('Hello');
J
Johannes Rieken 已提交
382 383 384
			}
		}));

M
Matt Bierner 已提交
385 386 387 388 389
		await rpcProtocol.sync();
		getHover(model, new EditorPosition(1, 1), CancellationToken.None).then(value => {
			assert.equal(value.length, 1);
			let [entry] = value;
			assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 });
J
Johannes Rieken 已提交
390 391 392
		});
	});

393

M
Matt Bierner 已提交
394
	test('HoverProvider, given range', async () => {
J
Johannes Rieken 已提交
395

M
Matt Bierner 已提交
396
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
397 398 399 400 401
			provideHover(): any {
				return new types.Hover('Hello', new types.Range(3, 0, 8, 7));
			}
		}));

M
Matt Bierner 已提交
402 403 404 405 406
		await rpcProtocol.sync();
		getHover(model, new EditorPosition(1, 1), CancellationToken.None).then(value => {
			assert.equal(value.length, 1);
			let [entry] = value;
			assert.deepEqual(entry.range, { startLineNumber: 4, startColumn: 1, endLineNumber: 9, endColumn: 8 });
J
Johannes Rieken 已提交
407 408 409 410
		});
	});


M
Matt Bierner 已提交
411
	test('HoverProvider, registration order', async () => {
M
Matt Bierner 已提交
412
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
413 414 415 416 417 418
			provideHover(): any {
				return new types.Hover('registered first');
			}
		}));


M
Matt Bierner 已提交
419
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
420 421 422 423
			provideHover(): any {
				return new types.Hover('registered second');
			}
		}));
J
Johannes Rieken 已提交
424

M
Matt Bierner 已提交
425 426 427 428 429 430
		await rpcProtocol.sync();
		const value = await getHover(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 2);
		let [first, second] = (value as modes.Hover[]);
		assert.equal(first.contents[0].value, 'registered second');
		assert.equal(second.contents[0].value, 'registered first');
J
Johannes Rieken 已提交
431 432
	});

433

M
Matt Bierner 已提交
434
	test('HoverProvider, evil provider', async () => {
J
Johannes Rieken 已提交
435

M
Matt Bierner 已提交
436
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
437
			provideHover(): any {
B
Benjamin Pasero 已提交
438
				throw new Error('evil');
J
Johannes Rieken 已提交
439 440
			}
		}));
M
Matt Bierner 已提交
441
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
442
			provideHover(): any {
B
Benjamin Pasero 已提交
443
				return new types.Hover('Hello');
J
Johannes Rieken 已提交
444 445 446
			}
		}));

M
Matt Bierner 已提交
447 448 449
		await rpcProtocol.sync();
		getHover(model, new EditorPosition(1, 1), CancellationToken.None).then(value => {
			assert.equal(value.length, 1);
450 451 452 453 454
		});
	});

	// --- occurrences

M
Matt Bierner 已提交
455
	test('Occurrences, data conversion', async () => {
456

M
Matt Bierner 已提交
457
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
458
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
459
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
460 461 462
			}
		}));

M
Matt Bierner 已提交
463 464 465 466 467 468
		await rpcProtocol.sync();
		let value = await getOccurrencesAtPosition(model, new EditorPosition(1, 2), CancellationToken.None);
		assert.equal(value.length, 1);
		let [entry] = value;
		assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 });
		assert.equal(entry.kind, modes.DocumentHighlightKind.Text);
469 470
	});

M
Matt Bierner 已提交
471
	test('Occurrences, order 1/2', async () => {
472

M
Matt Bierner 已提交
473
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
474
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
475
				return [];
476 477
			}
		}));
M
Matt Bierner 已提交
478
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, '*', new class implements vscode.DocumentHighlightProvider {
479
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
480
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
481 482 483
			}
		}));

M
Matt Bierner 已提交
484 485 486 487 488 489
		await rpcProtocol.sync();
		let value = await getOccurrencesAtPosition(model, new EditorPosition(1, 2), CancellationToken.None);
		assert.equal(value.length, 1);
		let [entry] = value;
		assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 });
		assert.equal(entry.kind, modes.DocumentHighlightKind.Text);
490 491
	});

M
Matt Bierner 已提交
492
	test('Occurrences, order 2/2', async () => {
493

M
Matt Bierner 已提交
494
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
495
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
496
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 2))];
497 498
			}
		}));
M
Matt Bierner 已提交
499
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, '*', new class implements vscode.DocumentHighlightProvider {
500
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
501
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
502 503 504
			}
		}));

M
Matt Bierner 已提交
505
		await rpcProtocol.sync();
506
		const value = (await getOccurrencesAtPosition(model, new EditorPosition(1, 2), CancellationToken.None))!;
M
Matt Bierner 已提交
507
		assert.equal(value.length, 1);
508
		const [entry] = value;
M
Matt Bierner 已提交
509 510
		assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 3 });
		assert.equal(entry.kind, modes.DocumentHighlightKind.Text);
511 512
	});

M
Matt Bierner 已提交
513
	test('Occurrences, evil provider', async () => {
514

M
Matt Bierner 已提交
515
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
516 517 518 519 520
			provideDocumentHighlights(): any {
				throw new Error('evil');
			}
		}));

M
Matt Bierner 已提交
521
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
522
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
523
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
524 525 526
			}
		}));

M
Matt Bierner 已提交
527 528 529
		await rpcProtocol.sync();
		const value = await getOccurrencesAtPosition(model, new EditorPosition(1, 2), CancellationToken.None);
		assert.equal(value.length, 1);
J
Johannes Rieken 已提交
530
	});
J
Johannes Rieken 已提交
531 532 533

	// --- references

M
Matt Bierner 已提交
534
	test('References, registration order', async () => {
J
Johannes Rieken 已提交
535

M
Matt Bierner 已提交
536
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
J
Johannes Rieken 已提交
537 538 539 540 541
			provideReferences(): any {
				return [new types.Location(URI.parse('far://register/first'), new types.Range(0, 0, 0, 0))];
			}
		}));

M
Matt Bierner 已提交
542
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
543 544 545 546
			provideReferences(): any {
				return [new types.Location(URI.parse('far://register/second'), new types.Range(0, 0, 0, 0))];
			}
		}));
J
Johannes Rieken 已提交
547

M
Matt Bierner 已提交
548 549 550 551 552 553
		await rpcProtocol.sync();
		let value = await provideReferences(model, new EditorPosition(1, 2), CancellationToken.None);
		assert.equal(value.length, 2);
		let [first, second] = value;
		assert.equal(first.uri.path, '/second');
		assert.equal(second.uri.path, '/first');
J
Johannes Rieken 已提交
554 555
	});

M
Matt Bierner 已提交
556
	test('References, data conversion', async () => {
J
Johannes Rieken 已提交
557

M
Matt Bierner 已提交
558
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
J
Johannes Rieken 已提交
559
			provideReferences(): any {
560
				return [new types.Location(model.uri, new types.Position(0, 0))];
J
Johannes Rieken 已提交
561 562 563
			}
		}));

M
Matt Bierner 已提交
564 565 566 567 568 569
		await rpcProtocol.sync();
		let value = await provideReferences(model, new EditorPosition(1, 2), CancellationToken.None);
		assert.equal(value.length, 1);
		let [item] = value;
		assert.deepEqual(item.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
		assert.equal(item.uri.toString(), model.uri.toString());
J
Johannes Rieken 已提交
570 571
	});

M
Matt Bierner 已提交
572
	test('References, evil provider', async () => {
J
Johannes Rieken 已提交
573

M
Matt Bierner 已提交
574
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
J
Johannes Rieken 已提交
575 576 577 578
			provideReferences(): any {
				throw new Error('evil');
			}
		}));
M
Matt Bierner 已提交
579
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
J
Johannes Rieken 已提交
580
			provideReferences(): any {
581
				return [new types.Location(model.uri, new types.Range(0, 0, 0, 0))];
J
Johannes Rieken 已提交
582 583 584
			}
		}));

M
Matt Bierner 已提交
585 586 587
		await rpcProtocol.sync();
		const value = await provideReferences(model, new EditorPosition(1, 2), CancellationToken.None);
		assert.equal(value.length, 1);
J
Johannes Rieken 已提交
588
	});
J
Johannes Rieken 已提交
589 590 591

	// --- quick fix

M
Matt Bierner 已提交
592
	test('Quick Fix, command data conversion', async () => {
J
Johannes Rieken 已提交
593

594
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, {
595
			provideCodeActions(): vscode.Command[] {
J
Johannes Rieken 已提交
596
				return [
597 598
					{ command: 'test1', title: 'Testing1' },
					{ command: 'test2', title: 'Testing2' }
J
Johannes Rieken 已提交
599 600 601 602
				];
			}
		}));

M
Matt Bierner 已提交
603 604 605 606 607 608 609 610
		await rpcProtocol.sync();
		let value = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
		assert.equal(value.length, 2);
		const [first, second] = value;
		assert.equal(first.title, 'Testing1');
		assert.equal(first.command.id, 'test1');
		assert.equal(second.title, 'Testing2');
		assert.equal(second.command.id, 'test2');
J
Johannes Rieken 已提交
611 612
	});

M
Matt Bierner 已提交
613
	test('Quick Fix, code action data conversion', async () => {
M
Matt Bierner 已提交
614

615
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, {
M
Matt Bierner 已提交
616 617 618 619 620 621 622 623 624 625 626
			provideCodeActions(): vscode.CodeAction[] {
				return [
					{
						title: 'Testing1',
						command: { title: 'Testing1Command', command: 'test1' },
						kind: types.CodeActionKind.Empty.append('test.scope')
					}
				];
			}
		}));

M
Matt Bierner 已提交
627 628 629 630 631 632 633 634
		await rpcProtocol.sync();
		let value = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
		assert.equal(value.length, 1);
		const [first] = value;
		assert.equal(first.title, 'Testing1');
		assert.equal(first.command.title, 'Testing1Command');
		assert.equal(first.command.id, 'test1');
		assert.equal(first.kind, 'test.scope');
M
Matt Bierner 已提交
635 636 637
	});


M
Matt Bierner 已提交
638
	test('Cannot read property \'id\' of undefined, #29469', async () => {
J
Johannes Rieken 已提交
639

M
Matt Bierner 已提交
640
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
J
Johannes Rieken 已提交
641 642 643 644
			provideCodeActions(): any {
				return [
					undefined,
					null,
M
Matt Bierner 已提交
645
					{ command: 'test', title: 'Testing' }
J
Johannes Rieken 已提交
646 647 648 649
				];
			}
		}));

M
Matt Bierner 已提交
650 651 652
		await rpcProtocol.sync();
		const value = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
		assert.equal(value.length, 1);
J
Johannes Rieken 已提交
653 654
	});

M
Matt Bierner 已提交
655
	test('Quick Fix, evil provider', async () => {
J
Johannes Rieken 已提交
656

M
Matt Bierner 已提交
657
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
J
Johannes Rieken 已提交
658 659 660 661
			provideCodeActions(): any {
				throw new Error('evil');
			}
		}));
M
Matt Bierner 已提交
662
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
J
Johannes Rieken 已提交
663
			provideCodeActions(): any {
M
Matt Bierner 已提交
664
				return [{ command: 'test', title: 'Testing' }];
J
Johannes Rieken 已提交
665 666 667
			}
		}));

M
Matt Bierner 已提交
668 669 670
		await rpcProtocol.sync();
		const value = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
		assert.equal(value.length, 1);
J
Johannes Rieken 已提交
671
	});
672 673 674

	// --- navigate types

M
Matt Bierner 已提交
675
	test('Navigate types, evil provider', async () => {
676

M
Matt Bierner 已提交
677
		disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
678 679 680 681 682
			provideWorkspaceSymbols(): any {
				throw new Error('evil');
			}
		}));

M
Matt Bierner 已提交
683
		disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
684
			provideWorkspaceSymbols(): any {
B
Benjamin Pasero 已提交
685
				return [new types.SymbolInformation('testing', types.SymbolKind.Array, new types.Range(0, 0, 1, 1))];
686 687 688
			}
		}));

M
Matt Bierner 已提交
689 690 691 692 693 694 695
		await rpcProtocol.sync();
		let value = await getWorkspaceSymbols('');
		assert.equal(value.length, 1);
		const [first] = value;
		const [, symbols] = first;
		assert.equal(symbols.length, 1);
		assert.equal(symbols[0].name, 'testing');
J
Johannes Rieken 已提交
696 697 698 699
	});

	// --- rename

M
Matt Bierner 已提交
700
	test('Rename, evil provider 0/2', async () => {
J
Johannes Rieken 已提交
701

M
Matt Bierner 已提交
702
		disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
703
			provideRenameEdits(): any {
J
Johannes Rieken 已提交
704
				throw new class Foo { };
J
Johannes Rieken 已提交
705 706 707
			}
		}));

M
Matt Bierner 已提交
708 709 710 711 712 713 714 715
		await rpcProtocol.sync();
		try {
			await rename(model, new EditorPosition(1, 1), 'newName');
			throw Error();
		}
		catch (err) {
			// expected
		}
J
Johannes Rieken 已提交
716 717
	});

M
Matt Bierner 已提交
718
	test('Rename, evil provider 1/2', async () => {
J
Johannes Rieken 已提交
719

M
Matt Bierner 已提交
720
		disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
721 722 723 724 725
			provideRenameEdits(): any {
				throw Error('evil');
			}
		}));

M
Matt Bierner 已提交
726 727 728
		await rpcProtocol.sync();
		const value = await rename(model, new EditorPosition(1, 1), 'newName');
		assert.equal(value.rejectReason, 'evil');
J
Johannes Rieken 已提交
729 730
	});

M
Matt Bierner 已提交
731
	test('Rename, evil provider 2/2', async () => {
J
Johannes Rieken 已提交
732

M
Matt Bierner 已提交
733
		disposables.push(extHost.registerRenameProvider(defaultExtension, '*', new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
734 735 736 737 738
			provideRenameEdits(): any {
				throw Error('evil');
			}
		}));

M
Matt Bierner 已提交
739
		disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
740 741
			provideRenameEdits(): any {
				let edit = new types.WorkspaceEdit();
742
				edit.replace(model.uri, new types.Range(0, 0, 0, 0), 'testing');
J
Johannes Rieken 已提交
743 744 745 746
				return edit;
			}
		}));

M
Matt Bierner 已提交
747 748 749
		await rpcProtocol.sync();
		const value = await rename(model, new EditorPosition(1, 1), 'newName');
		assert.equal(value.edits.length, 1);
J
Johannes Rieken 已提交
750 751
	});

M
Matt Bierner 已提交
752
	test('Rename, ordering', async () => {
J
Johannes Rieken 已提交
753

M
Matt Bierner 已提交
754
		disposables.push(extHost.registerRenameProvider(defaultExtension, '*', new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
755 756
			provideRenameEdits(): any {
				let edit = new types.WorkspaceEdit();
757 758
				edit.replace(model.uri, new types.Range(0, 0, 0, 0), 'testing');
				edit.replace(model.uri, new types.Range(1, 0, 1, 0), 'testing');
J
Johannes Rieken 已提交
759 760 761 762
				return edit;
			}
		}));

M
Matt Bierner 已提交
763
		disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
764 765 766 767 768
			provideRenameEdits(): any {
				return;
			}
		}));

M
Matt Bierner 已提交
769 770 771 772 773 774
		await rpcProtocol.sync();
		const value = await rename(model, new EditorPosition(1, 1), 'newName');
		// least relevant rename provider
		assert.equal(value.edits.length, 2);
		assert.equal((<modes.ResourceTextEdit>value.edits[0]).edits.length, 1);
		assert.equal((<modes.ResourceTextEdit>value.edits[1]).edits.length, 1);
J
Johannes Rieken 已提交
775
	});
776 777 778

	// --- parameter hints

M
Matt Bierner 已提交
779
	test('Parameter Hints, order', async () => {
J
Johannes Rieken 已提交
780

M
Matt Bierner 已提交
781
		disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
J
Johannes Rieken 已提交
782 783 784 785 786
			provideSignatureHelp(): any {
				return undefined;
			}
		}, []));

M
Matt Bierner 已提交
787
		disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
J
Johannes Rieken 已提交
788
			provideSignatureHelp(): vscode.SignatureHelp {
789 790 791 792 793
				return {
					signatures: [],
					activeParameter: 0,
					activeSignature: 0
				};
J
Johannes Rieken 已提交
794 795 796
			}
		}, []));

M
Matt Bierner 已提交
797 798 799
		await rpcProtocol.sync();
		const value = await provideSignatureHelp(model, new EditorPosition(1, 1), { triggerKind: modes.SignatureHelpTriggerKind.Invoke, isRetrigger: false }, CancellationToken.None);
		assert.ok(value);
J
Johannes Rieken 已提交
800
	});
801

M
Matt Bierner 已提交
802
	test('Parameter Hints, evil provider', async () => {
803

M
Matt Bierner 已提交
804
		disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
805 806 807 808 809
			provideSignatureHelp(): any {
				throw new Error('evil');
			}
		}, []));

M
Matt Bierner 已提交
810 811 812
		await rpcProtocol.sync();
		const value = await provideSignatureHelp(model, new EditorPosition(1, 1), { triggerKind: modes.SignatureHelpTriggerKind.Invoke, isRetrigger: false }, CancellationToken.None);
		assert.equal(value, undefined);
813 814 815 816
	});

	// --- suggestions

M
Matt Bierner 已提交
817
	test('Suggest, order 1/3', async () => {
818

M
Matt Bierner 已提交
819
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, '*', new class implements vscode.CompletionItemProvider {
820 821 822 823 824
			provideCompletionItems(): any {
				return [new types.CompletionItem('testing1')];
			}
		}, []));

M
Matt Bierner 已提交
825
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
826 827 828 829 830
			provideCompletionItems(): any {
				return [new types.CompletionItem('testing2')];
			}
		}, []));

M
Matt Bierner 已提交
831 832 833 834
		await rpcProtocol.sync();
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), 'none');
		assert.equal(value.length, 1);
		assert.equal(value[0].completion.insertText, 'testing2');
835 836
	});

M
Matt Bierner 已提交
837
	test('Suggest, order 2/3', async () => {
838

M
Matt Bierner 已提交
839
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, '*', new class implements vscode.CompletionItemProvider {
840 841 842 843 844
			provideCompletionItems(): any {
				return [new types.CompletionItem('weak-selector')]; // weaker selector but result
			}
		}, []));

M
Matt Bierner 已提交
845
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
846 847 848 849 850
			provideCompletionItems(): any {
				return []; // stronger selector but not a good result;
			}
		}, []));

M
Matt Bierner 已提交
851 852 853 854
		await rpcProtocol.sync();
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), 'none');
		assert.equal(value.length, 1);
		assert.equal(value[0].completion.insertText, 'weak-selector');
B
Benjamin Pasero 已提交
855
	});
856

M
Matt Bierner 已提交
857
	test('Suggest, order 2/3', async () => {
858

M
Matt Bierner 已提交
859
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
860 861 862 863 864
			provideCompletionItems(): any {
				return [new types.CompletionItem('strong-1')];
			}
		}, []));

M
Matt Bierner 已提交
865
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
866 867 868 869 870
			provideCompletionItems(): any {
				return [new types.CompletionItem('strong-2')];
			}
		}, []));

M
Matt Bierner 已提交
871 872 873 874 875
		await rpcProtocol.sync();
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), 'none');
		assert.equal(value.length, 2);
		assert.equal(value[0].completion.insertText, 'strong-1'); // sort by label
		assert.equal(value[1].completion.insertText, 'strong-2');
B
Benjamin Pasero 已提交
876
	});
877

M
Matt Bierner 已提交
878
	test('Suggest, evil provider', async () => {
879

M
Matt Bierner 已提交
880
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
881 882 883 884 885
			provideCompletionItems(): any {
				throw new Error('evil');
			}
		}, []));

M
Matt Bierner 已提交
886
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
887 888 889 890 891 892
			provideCompletionItems(): any {
				return [new types.CompletionItem('testing')];
			}
		}, []));


M
Matt Bierner 已提交
893 894 895
		await rpcProtocol.sync();
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), 'none');
		assert.equal(value[0].container.incomplete, undefined);
896
	});
897

M
Matt Bierner 已提交
898
	test('Suggest, CompletionList', async () => {
899

M
Matt Bierner 已提交
900
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
901
			provideCompletionItems(): any {
J
Johannes Rieken 已提交
902
				return new types.CompletionList([<any>new types.CompletionItem('hello')], true);
903 904 905
			}
		}, []));

M
Matt Bierner 已提交
906 907 908
		await rpcProtocol.sync();
		provideSuggestionItems(model, new EditorPosition(1, 1), 'none').then(value => {
			assert.equal(value[0].container.incomplete, true);
909 910 911
		});
	});

912 913
	// --- format

J
Johannes Rieken 已提交
914 915 916 917 918 919
	const NullWorkerService = new class extends mock<IEditorWorkerService>() {
		computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[] | null | undefined): Promise<modes.TextEdit[] | null | undefined> {
			return Promise.resolve(edits);
		}
	};

M
Matt Bierner 已提交
920
	test('Format Doc, data conversion', async () => {
M
Matt Bierner 已提交
921
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
922
			provideDocumentFormattingEdits(): any {
923
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing'), types.TextEdit.setEndOfLine(types.EndOfLine.LF)];
924 925 926
			}
		}));

M
Matt Bierner 已提交
927
		await rpcProtocol.sync();
928
		let value = await getDocumentFormattingEdits(NullTelemetryService, NullWorkerService, model, { insertSpaces: true, tabSize: 4 }, FormatMode.Auto, CancellationToken.None);
M
Matt Bierner 已提交
929 930 931 932 933 934 935
		assert.equal(value.length, 2);
		let [first, second] = value;
		assert.equal(first.text, 'testing');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
		assert.equal(second.eol, EndOfLineSequence.LF);
		assert.equal(second.text, '');
		assert.deepEqual(second.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
936 937
	});

M
Matt Bierner 已提交
938
	test('Format Doc, evil provider', async () => {
M
Matt Bierner 已提交
939
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
940 941 942 943 944
			provideDocumentFormattingEdits(): any {
				throw new Error('evil');
			}
		}));

M
Matt Bierner 已提交
945
		await rpcProtocol.sync();
946
		return getDocumentFormattingEdits(NullTelemetryService, NullWorkerService, model, { insertSpaces: true, tabSize: 4 }, FormatMode.Auto, CancellationToken.None);
947 948
	});

M
Matt Bierner 已提交
949
	test('Format Doc, order', async () => {
950

M
Matt Bierner 已提交
951
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
952 953 954 955 956
			provideDocumentFormattingEdits(): any {
				return undefined;
			}
		}));

M
Matt Bierner 已提交
957
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
958 959 960 961 962
			provideDocumentFormattingEdits(): any {
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')];
			}
		}));

M
Matt Bierner 已提交
963
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
964 965 966 967 968
			provideDocumentFormattingEdits(): any {
				return undefined;
			}
		}));

M
Matt Bierner 已提交
969
		await rpcProtocol.sync();
970
		let value = await getDocumentFormattingEdits(NullTelemetryService, NullWorkerService, model, { insertSpaces: true, tabSize: 4 }, FormatMode.Auto, CancellationToken.None);
M
Matt Bierner 已提交
971 972 973 974
		assert.equal(value.length, 1);
		let [first] = value;
		assert.equal(first.text, 'testing');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
975 976
	});

M
Matt Bierner 已提交
977
	test('Format Range, data conversion', async () => {
M
Matt Bierner 已提交
978
		disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
979
			provideDocumentRangeFormattingEdits(): any {
J
Johannes Rieken 已提交
980
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')];
981 982 983
			}
		}));

M
Matt Bierner 已提交
984
		await rpcProtocol.sync();
985
		let value = await getDocumentRangeFormattingEdits(NullTelemetryService, NullWorkerService, model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }, FormatMode.Auto, CancellationToken.None);
M
Matt Bierner 已提交
986 987 988 989
		assert.equal(value.length, 1);
		let [first] = value;
		assert.equal(first.text, 'testing');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
B
Benjamin Pasero 已提交
990
	});
991

M
Matt Bierner 已提交
992
	test('Format Range, + format_doc', async () => {
M
Matt Bierner 已提交
993
		disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
994
			provideDocumentRangeFormattingEdits(): any {
J
Johannes Rieken 已提交
995
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'range')];
996 997
			}
		}));
M
Matt Bierner 已提交
998
		disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
999 1000 1001 1002
			provideDocumentRangeFormattingEdits(): any {
				return [new types.TextEdit(new types.Range(2, 3, 4, 5), 'range2')];
			}
		}));
M
Matt Bierner 已提交
1003
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
1004 1005 1006 1007
			provideDocumentFormattingEdits(): any {
				return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'doc')];
			}
		}));
M
Matt Bierner 已提交
1008
		await rpcProtocol.sync();
1009
		let value = await getDocumentRangeFormattingEdits(NullTelemetryService, NullWorkerService, model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }, FormatMode.Auto, CancellationToken.None);
M
Matt Bierner 已提交
1010 1011 1012 1013 1014 1015 1016
		assert.equal(value.length, 1);
		let [first] = value;
		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);
1017 1018
	});

M
Matt Bierner 已提交
1019
	test('Format Range, evil provider', async () => {
M
Matt Bierner 已提交
1020
		disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
1021 1022 1023 1024 1025
			provideDocumentRangeFormattingEdits(): any {
				throw new Error('evil');
			}
		}));

M
Matt Bierner 已提交
1026
		await rpcProtocol.sync();
1027
		return getDocumentRangeFormattingEdits(NullTelemetryService, NullWorkerService, model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }, FormatMode.Auto, CancellationToken.None);
B
Benjamin Pasero 已提交
1028
	});
1029

M
Matt Bierner 已提交
1030
	test('Format on Type, data conversion', async () => {
1031

M
Matt Bierner 已提交
1032
		disposables.push(extHost.registerOnTypeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.OnTypeFormattingEditProvider {
1033 1034 1035 1036 1037
			provideOnTypeFormattingEdits(): any {
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), arguments[2])];
			}
		}, [';']));

M
Matt Bierner 已提交
1038
		await rpcProtocol.sync();
J
Johannes Rieken 已提交
1039
		let value = await getOnTypeFormattingEdits(NullTelemetryService, NullWorkerService, model, new EditorPosition(1, 1), ';', { insertSpaces: true, tabSize: 2 });
M
Matt Bierner 已提交
1040 1041 1042 1043
		assert.equal(value.length, 1);
		let [first] = value;
		assert.equal(first.text, ';');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
1044
	});
J
Johannes Rieken 已提交
1045

M
Matt Bierner 已提交
1046
	test('Links, data conversion', async () => {
J
Johannes Rieken 已提交
1047

M
Matt Bierner 已提交
1048
		disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
J
Johannes Rieken 已提交
1049
			provideDocumentLinks() {
1050
				return [new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'))];
J
Johannes Rieken 已提交
1051 1052 1053
			}
		}));

M
Matt Bierner 已提交
1054 1055 1056 1057 1058 1059
		await rpcProtocol.sync();
		let value = await getLinks(model, CancellationToken.None);
		assert.equal(value.length, 1);
		let [first] = value;
		assert.equal(first.url, 'foo:bar#3');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 });
J
Johannes Rieken 已提交
1060 1061
	});

M
Matt Bierner 已提交
1062
	test('Links, evil provider', async () => {
J
Johannes Rieken 已提交
1063

M
Matt Bierner 已提交
1064
		disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
J
Johannes Rieken 已提交
1065
			provideDocumentLinks() {
1066
				return [new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'))];
J
Johannes Rieken 已提交
1067 1068 1069
			}
		}));

M
Matt Bierner 已提交
1070
		disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
J
Johannes Rieken 已提交
1071 1072 1073 1074 1075
			provideDocumentLinks(): any {
				throw new Error();
			}
		}));

M
Matt Bierner 已提交
1076 1077 1078 1079 1080 1081
		await rpcProtocol.sync();
		let value = await getLinks(model, CancellationToken.None);
		assert.equal(value.length, 1);
		let [first] = value;
		assert.equal(first.url, 'foo:bar#3');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 });
J
Johannes Rieken 已提交
1082
	});
1083

M
Matt Bierner 已提交
1084
	test('Document colors, data conversion', async () => {
1085

M
Matt Bierner 已提交
1086
		disposables.push(extHost.registerColorProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentColorProvider {
1087 1088
			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))];
M
Matt Bierner 已提交
1089
			}
1090 1091 1092 1093 1094
			provideColorPresentations(color: vscode.Color, context: { range: vscode.Range, document: vscode.TextDocument }): vscode.ColorPresentation[] {
				return [];
			}
		}));

M
Matt Bierner 已提交
1095 1096 1097 1098 1099 1100
		await rpcProtocol.sync();
		let value = await getColors(model, CancellationToken.None);
		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 });
1101
	});
1102 1103 1104

	// -- selection ranges

M
Matt Bierner 已提交
1105
	test('Selection Ranges, data conversion', async () => {
M
Matt Bierner 已提交
1106
		disposables.push(extHost.registerSelectionRangeProvider(defaultExtension, defaultSelector, new class implements vscode.SelectionRangeProvider {
1107
			provideSelectionRanges() {
1108
				return [[
1109 1110
					new types.SelectionRange(new types.Range(0, 10, 0, 18), types.SelectionRangeKind.Empty),
					new types.SelectionRange(new types.Range(0, 2, 0, 20), types.SelectionRangeKind.Empty)
1111
				]];
1112 1113 1114 1115 1116
			}
		}));

		await rpcProtocol.sync();

1117 1118 1119
		provideSelectionRanges(model, [new Position(1, 17)], CancellationToken.None).then(ranges => {
			assert.equal(ranges.length, 1);
			assert.ok(ranges[0].length >= 2);
1120 1121
		});
	});
J
tslint  
Johannes Rieken 已提交
1122
});