extHostLanguageFeatures.test.ts 43.8 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
import { rename } from 'vs/editor/contrib/rename/rename';
import { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
35
import { provideSuggestionItems, CompletionOptions } 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
import { dispose } from 'vs/base/common/lifecycle';
53 54

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

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

J
Johannes Rieken 已提交
71 72


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

	suiteSetup(() => {

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

		// 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 已提交
86
				trackObject(_obj: any) {
87 88 89 90 91
					// nothing
				}
			});
			inst = instantiationService;
		}
J
Johannes Rieken 已提交
92

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

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

110 111
		const heapService = new ExtHostHeapService();

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

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

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

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

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

131 132
	teardown(() => {
		disposables = dispose(disposables);
A
Alex Dima 已提交
133
		return rpcProtocol.sync();
134 135
	});

136 137
	// --- outline

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

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

	});

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

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

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

M
Matt Bierner 已提交
177 178 179 180 181 182
		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 });
183
	});
184 185 186

	// --- code lens

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

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

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

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

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

M
Matt Bierner 已提交
218 219 220
		await rpcProtocol.sync();
		const value = await getCodeLensData(model, CancellationToken.None);
		assert.equal(value.length, 1);
221 222 223 224
		const 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');
225 226
	});

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

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

M
Matt Bierner 已提交
235 236 237 238
		await rpcProtocol.sync();
		const value = await getCodeLensData(model, CancellationToken.None);
		assert.equal(value.length, 1);
		let data = value[0];
239 240 241
		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!!');
242
	});
J
Johannes Rieken 已提交
243 244 245

	// --- definition

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

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

M
Matt Bierner 已提交
254 255 256 257 258 259
		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 已提交
260 261
	});

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

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

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

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

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

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

M
Matt Bierner 已提交
294 295 296 297 298 299
		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 已提交
300 301
	});

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

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

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

320 321
	// -- declaration

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

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

M
Matt Bierner 已提交
330 331 332 333 334 335
		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());
336 337
	});

338
	// --- implementation
339

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

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

M
Matt Bierner 已提交
348 349 350 351 352 353
		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());
354 355 356 357
	});

	// --- type definition

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

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

M
Matt Bierner 已提交
366 367 368 369 370 371
		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());
372 373
	});

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

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

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

M
Matt Bierner 已提交
384 385 386 387 388
		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 已提交
389 390 391
		});
	});

392

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

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

M
Matt Bierner 已提交
401 402 403 404 405
		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 已提交
406 407 408 409
		});
	});


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


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

M
Matt Bierner 已提交
424 425 426 427 428 429
		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 已提交
430 431
	});

432

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

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

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

	// --- occurrences

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

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

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

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

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

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

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

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

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

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

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

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

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

	// --- references

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

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

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

M
Matt Bierner 已提交
547 548 549 550 551 552
		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 已提交
553 554
	});

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

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

M
Matt Bierner 已提交
563 564 565 566 567 568
		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 已提交
569 570
	});

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

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

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

	// --- quick fix

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

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

M
Matt Bierner 已提交
602 603 604 605 606
		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');
607
		assert.equal(first.command!.id, 'test1');
M
Matt Bierner 已提交
608
		assert.equal(second.title, 'Testing2');
609
		assert.equal(second.command!.id, 'test2');
J
Johannes Rieken 已提交
610 611
	});

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

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

M
Matt Bierner 已提交
626 627 628 629 630
		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');
631 632
		assert.equal(first.command!.title, 'Testing1Command');
		assert.equal(first.command!.id, 'test1');
M
Matt Bierner 已提交
633
		assert.equal(first.kind, 'test.scope');
M
Matt Bierner 已提交
634 635 636
	});


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

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

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

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

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

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

	// --- navigate types

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

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

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

M
Matt Bierner 已提交
688 689 690 691 692 693 694
		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 已提交
695 696 697 698
	});

	// --- rename

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

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

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

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

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

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

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

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

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

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

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

M
Matt Bierner 已提交
753
		disposables.push(extHost.registerRenameProvider(defaultExtension, '*', new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
754 755
			provideRenameEdits(): any {
				let edit = new types.WorkspaceEdit();
756 757
				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 已提交
758 759 760 761
				return edit;
			}
		}));

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

M
Matt Bierner 已提交
768 769 770 771 772 773
		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 已提交
774
	});
775 776 777

	// --- parameter hints

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

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

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

M
Matt Bierner 已提交
796 797 798
		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 已提交
799
	});
800

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

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

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

	// --- suggestions

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

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

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

M
Matt Bierner 已提交
830
		await rpcProtocol.sync();
831
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
M
Matt Bierner 已提交
832 833
		assert.equal(value.length, 1);
		assert.equal(value[0].completion.insertText, 'testing2');
834 835
	});

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

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

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

M
Matt Bierner 已提交
850
		await rpcProtocol.sync();
851
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
M
Matt Bierner 已提交
852 853
		assert.equal(value.length, 1);
		assert.equal(value[0].completion.insertText, 'weak-selector');
B
Benjamin Pasero 已提交
854
	});
855

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

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

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

M
Matt Bierner 已提交
870
		await rpcProtocol.sync();
871
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
M
Matt Bierner 已提交
872 873 874
		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 已提交
875
	});
876

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

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

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


M
Matt Bierner 已提交
892
		await rpcProtocol.sync();
893
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
M
Matt Bierner 已提交
894
		assert.equal(value[0].container.incomplete, undefined);
895
	});
896

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

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

M
Matt Bierner 已提交
905
		await rpcProtocol.sync();
906
		provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet))).then(value => {
M
Matt Bierner 已提交
907
			assert.equal(value[0].container.incomplete, true);
908 909 910
		});
	});

911 912
	// --- format

J
Johannes Rieken 已提交
913 914 915 916 917 918
	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 已提交
919
	test('Format Doc, data conversion', async () => {
M
Matt Bierner 已提交
920
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
921
			provideDocumentFormattingEdits(): any {
922
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing'), types.TextEdit.setEndOfLine(types.EndOfLine.LF)];
923 924 925
			}
		}));

M
Matt Bierner 已提交
926
		await rpcProtocol.sync();
927
		let value = (await getDocumentFormattingEdits(NullTelemetryService, NullWorkerService, model, { insertSpaces: true, tabSize: 4 }, FormatMode.Auto, CancellationToken.None))!;
M
Matt Bierner 已提交
928 929 930 931 932 933 934
		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 });
935 936
	});

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

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

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

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

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

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

M
Matt Bierner 已提交
968
		await rpcProtocol.sync();
969
		let value = (await getDocumentFormattingEdits(NullTelemetryService, NullWorkerService, model, { insertSpaces: true, tabSize: 4 }, FormatMode.Auto, CancellationToken.None))!;
M
Matt Bierner 已提交
970 971 972 973
		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 });
974 975
	});

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

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

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

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

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

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

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

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

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

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

M
Matt Bierner 已提交
1053 1054 1055 1056 1057 1058
		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 已提交
1059 1060
	});

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

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

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

M
Matt Bierner 已提交
1075 1076 1077 1078 1079 1080
		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 已提交
1081
	});
1082

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

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

M
Matt Bierner 已提交
1094 1095 1096 1097 1098 1099
		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 });
1100
	});
1101 1102 1103

	// -- selection ranges

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

		await rpcProtocol.sync();

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