extHostLanguageFeatures.test.ts 43.7 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/common/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/common/extHostLanguageFeatures';
J
Johannes Rieken 已提交
18
import { MainThreadLanguageFeatures } from 'vs/workbench/api/browser/mainThreadLanguageFeatures';
J
Johannes Rieken 已提交
19
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
J
Johannes Rieken 已提交
20
import { MainThreadCommands } from 'vs/workbench/api/browser/mainThreadCommands';
J
Johannes Rieken 已提交
21 22
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
23
import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen';
24
import * as modes from 'vs/editor/common/modes';
25
import { getCodeLensData } from 'vs/editor/contrib/codelens/codelens';
26
import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition, getDeclarationsAtPosition } from 'vs/editor/contrib/goToDefinition/goToDefinition';
27 28 29
import { getHover } from 'vs/editor/contrib/hover/getHover';
import { getOccurrencesAtPosition } from 'vs/editor/contrib/wordHighlighter/wordHighlighter';
import { provideReferences } from 'vs/editor/contrib/referenceSearch/referenceSearch';
30
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
31
import { getWorkspaceSymbols } from 'vs/workbench/contrib/search/common/search';
32 33
import { rename } from 'vs/editor/contrib/rename/rename';
import { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
34
import { provideSuggestionItems, CompletionOptions } from 'vs/editor/contrib/suggest/suggest';
35
import { getDocumentFormattingEditsUntilResult, getDocumentRangeFormattingEditsUntilResult, getOnTypeFormattingEdits } from 'vs/editor/contrib/format/format';
36
import { getLinks } from 'vs/editor/contrib/links/getLinks';
37
import { MainContext, ExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
J
Johannes Rieken 已提交
38
import { ExtHostDiagnostics } from 'vs/workbench/api/common/extHostDiagnostics';
39
import * as vscode from 'vscode';
B
Benjamin Pasero 已提交
40
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
41
import { NullLogService } from 'vs/platform/log/common/log';
A
Alex Dima 已提交
42
import { ITextModel, EndOfLineSequence } from 'vs/editor/common/model';
43
import { getColors } from 'vs/editor/contrib/colorPicker/color';
44
import { CancellationToken } from 'vs/base/common/cancellation';
45
import { nullExtensionDescription as defaultExtension } from 'vs/workbench/services/extensions/common/extensions';
46
import { provideSelectionRanges } from 'vs/editor/contrib/smartSelect/smartSelect';
J
Johannes Rieken 已提交
47 48
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
49
import { dispose } from 'vs/base/common/lifecycle';
50
import { withNullAsUndefined } from 'vs/base/common/types';
51 52

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

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

J
Johannes Rieken 已提交
69 70


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

	suiteSetup(() => {

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

		// Use IInstantiationService to get typechecking when instantiating
		let inst: IInstantiationService;
		{
			let instantiationService = new TestInstantiationService();
			instantiationService.stub(IMarkerService, MarkerService);
			inst = instantiationService;
		}
J
Johannes Rieken 已提交
84

85 86 87
		originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
		setUnexpectedErrorHandler(() => { });

88
		const extHostDocumentsAndEditors = new ExtHostDocumentsAndEditors(rpcProtocol);
J
Johannes Rieken 已提交
89 90 91 92 93
		extHostDocumentsAndEditors.$acceptDocumentsAndEditorsDelta({
			addedDocuments: [{
				isDirty: false,
				versionId: model.getVersionId(),
				modeId: model.getLanguageIdentifier().language,
94
				uri: model.uri,
J
Johannes Rieken 已提交
95 96 97
				lines: model.getValue().split(model.getEOL()),
				EOL: model.getEOL(),
			}]
98
		});
A
Alex Dima 已提交
99 100
		const extHostDocuments = new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors);
		rpcProtocol.set(ExtHostContext.ExtHostDocuments, extHostDocuments);
101

102
		const commands = new ExtHostCommands(rpcProtocol, new NullLogService());
A
Alex Dima 已提交
103 104
		rpcProtocol.set(ExtHostContext.ExtHostCommands, commands);
		rpcProtocol.set(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, rpcProtocol));
105

A
Alex Dima 已提交
106 107
		const diagnostics = new ExtHostDiagnostics(rpcProtocol);
		rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
108

109
		extHost = new ExtHostLanguageFeatures(rpcProtocol, null, extHostDocuments, commands, diagnostics, new NullLogService());
A
Alex Dima 已提交
110
		rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost);
111

A
Alex Dima 已提交
112
		mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, inst.createInstance(MainThreadLanguageFeatures, rpcProtocol));
113 114 115 116
	});

	suiteTeardown(() => {
		setUnexpectedErrorHandler(originalErrorHandler);
117
		model.dispose();
J
Johannes Rieken 已提交
118
		mainThread.dispose();
119 120
	});

121 122
	teardown(() => {
		disposables = dispose(disposables);
A
Alex Dima 已提交
123
		return rpcProtocol.sync();
124 125
	});

126 127
	// --- outline

M
Matt Bierner 已提交
128
	test('DocumentSymbols, register/deregister', async () => {
129
		assert.equal(modes.DocumentSymbolProviderRegistry.all(model).length, 0);
M
Matt Bierner 已提交
130
		let d1 = extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
131
			provideDocumentSymbols() {
A
Alex Dima 已提交
132
				return <vscode.SymbolInformation[]>[];
133 134 135
			}
		});

M
Matt Bierner 已提交
136 137 138 139
		await rpcProtocol.sync();
		assert.equal(modes.DocumentSymbolProviderRegistry.all(model).length, 1);
		d1.dispose();
		return rpcProtocol.sync();
140 141 142

	});

M
Matt Bierner 已提交
143
	test('DocumentSymbols, evil provider', async () => {
M
Matt Bierner 已提交
144
		disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
145 146 147 148
			provideDocumentSymbols(): any {
				throw new Error('evil document symbol provider');
			}
		}));
M
Matt Bierner 已提交
149
		disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
150
			provideDocumentSymbols(): any {
151
				return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))];
152 153 154
			}
		}));

M
Matt Bierner 已提交
155 156 157
		await rpcProtocol.sync();
		const value = await getDocumentSymbols(model, true, CancellationToken.None);
		assert.equal(value.length, 1);
158 159
	});

M
Matt Bierner 已提交
160
	test('DocumentSymbols, data conversion', async () => {
M
Matt Bierner 已提交
161
		disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
162
			provideDocumentSymbols(): any {
163
				return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))];
164 165 166
			}
		}));

M
Matt Bierner 已提交
167 168 169 170 171 172
		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 });
173
	});
174 175 176

	// --- code lens

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

M
Matt Bierner 已提交
179
		disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
J
tslint  
Johannes Rieken 已提交
180
			provideCodeLenses(): any {
B
Benjamin Pasero 已提交
181
				throw new Error('evil');
182 183
			}
		}));
M
Matt Bierner 已提交
184
		disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
185 186 187 188 189
			provideCodeLenses() {
				return [new types.CodeLens(new types.Range(0, 0, 0, 0))];
			}
		}));

M
Matt Bierner 已提交
190 191
		await rpcProtocol.sync();
		const value = await getCodeLensData(model, CancellationToken.None);
192
		assert.equal(value.lenses.length, 1);
193 194
	});

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

M
Matt Bierner 已提交
197
		disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
J
tslint  
Johannes Rieken 已提交
198
			provideCodeLenses(): any {
199 200 201
				return [new types.CodeLens(
					new types.Range(0, 0, 0, 0),
					{ command: 'id', title: 'Title' })];
M
Matt Bierner 已提交
202
			}
J
tslint  
Johannes Rieken 已提交
203
			resolveCodeLens(): any {
204 205 206 207
				assert.ok(false, 'do not resolve');
			}
		}));

M
Matt Bierner 已提交
208 209
		await rpcProtocol.sync();
		const value = await getCodeLensData(model, CancellationToken.None);
210 211
		assert.equal(value.lenses.length, 1);
		const [data] = value.lenses;
212 213 214
		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');
215 216
	});

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

M
Matt Bierner 已提交
219
		disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
220 221 222 223 224
			provideCodeLenses() {
				return [new types.CodeLens(new types.Range(0, 0, 0, 0))];
			}
		}));

M
Matt Bierner 已提交
225 226
		await rpcProtocol.sync();
		const value = await getCodeLensData(model, CancellationToken.None);
227 228
		assert.equal(value.lenses.length, 1);
		let [data] = value.lenses;
229 230 231
		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!!');
232
	});
J
Johannes Rieken 已提交
233 234 235

	// --- definition

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

M
Matt Bierner 已提交
238
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
239
			provideDefinition(): any {
240
				return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
J
Johannes Rieken 已提交
241 242 243
			}
		}));

M
Matt Bierner 已提交
244 245 246 247 248 249
		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 已提交
250 251
	});

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

M
Matt Bierner 已提交
254
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
255
			provideDefinition(): any {
256
				return [new types.Location(model.uri, new types.Range(1, 1, 1, 1))];
J
Johannes Rieken 已提交
257 258
			}
		}));
M
Matt Bierner 已提交
259
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
260
			provideDefinition(): any {
261
				return new types.Location(model.uri, new types.Range(1, 1, 1, 1));
J
Johannes Rieken 已提交
262 263 264
			}
		}));

M
Matt Bierner 已提交
265 266 267
		await rpcProtocol.sync();
		const value = await getDefinitionsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 2);
J
Johannes Rieken 已提交
268 269
	});

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

M
Matt Bierner 已提交
272
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
273 274 275 276 277
			provideDefinition(): any {
				return [new types.Location(URI.parse('far://first'), new types.Range(2, 3, 4, 5))];
			}
		}));

M
Matt Bierner 已提交
278
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
279 280 281 282
			provideDefinition(): any {
				return new types.Location(URI.parse('far://second'), new types.Range(1, 2, 3, 4));
			}
		}));
J
Johannes Rieken 已提交
283

M
Matt Bierner 已提交
284 285 286 287 288 289
		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 已提交
290 291
	});

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

M
Matt Bierner 已提交
294
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
295
			provideDefinition(): any {
B
Benjamin Pasero 已提交
296
				throw new Error('evil provider');
J
Johannes Rieken 已提交
297 298
			}
		}));
M
Matt Bierner 已提交
299
		disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
J
Johannes Rieken 已提交
300
			provideDefinition(): any {
301
				return new types.Location(model.uri, new types.Range(1, 1, 1, 1));
J
Johannes Rieken 已提交
302 303 304
			}
		}));

M
Matt Bierner 已提交
305 306 307
		await rpcProtocol.sync();
		const value = await getDefinitionsAtPosition(model, new EditorPosition(1, 1), CancellationToken.None);
		assert.equal(value.length, 1);
J
Johannes Rieken 已提交
308
	});
J
Johannes Rieken 已提交
309

310 311
	// -- declaration

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

M
Matt Bierner 已提交
314
		disposables.push(extHost.registerDeclarationProvider(defaultExtension, defaultSelector, new class implements vscode.DeclarationProvider {
315 316 317 318 319
			provideDeclaration(): any {
				return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
			}
		}));

M
Matt Bierner 已提交
320 321 322 323 324 325
		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());
326 327
	});

328
	// --- implementation
329

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

M
Matt Bierner 已提交
332
		disposables.push(extHost.registerImplementationProvider(defaultExtension, defaultSelector, new class implements vscode.ImplementationProvider {
M
Matt Bierner 已提交
333
			provideImplementation(): any {
334 335 336 337
				return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
			}
		}));

M
Matt Bierner 已提交
338 339 340 341 342 343
		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());
344 345 346 347
	});

	// --- type definition

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

M
Matt Bierner 已提交
350
		disposables.push(extHost.registerTypeDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.TypeDefinitionProvider {
351 352 353 354 355
			provideTypeDefinition(): any {
				return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
			}
		}));

M
Matt Bierner 已提交
356 357 358 359 360 361
		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());
362 363
	});

J
Johannes Rieken 已提交
364 365
	// --- extra info

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

M
Matt Bierner 已提交
368
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
369
			provideHover(): any {
B
Benjamin Pasero 已提交
370
				return new types.Hover('Hello');
J
Johannes Rieken 已提交
371 372 373
			}
		}));

M
Matt Bierner 已提交
374 375 376 377 378
		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 已提交
379 380 381
		});
	});

382

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

M
Matt Bierner 已提交
385
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
386 387 388 389 390
			provideHover(): any {
				return new types.Hover('Hello', new types.Range(3, 0, 8, 7));
			}
		}));

M
Matt Bierner 已提交
391 392 393 394 395
		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 已提交
396 397 398 399
		});
	});


M
Matt Bierner 已提交
400
	test('HoverProvider, registration order', async () => {
M
Matt Bierner 已提交
401
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
402 403 404 405 406 407
			provideHover(): any {
				return new types.Hover('registered first');
			}
		}));


M
Matt Bierner 已提交
408
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
409 410 411 412
			provideHover(): any {
				return new types.Hover('registered second');
			}
		}));
J
Johannes Rieken 已提交
413

M
Matt Bierner 已提交
414 415 416 417 418 419
		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 已提交
420 421
	});

422

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

M
Matt Bierner 已提交
425
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
426
			provideHover(): any {
B
Benjamin Pasero 已提交
427
				throw new Error('evil');
J
Johannes Rieken 已提交
428 429
			}
		}));
M
Matt Bierner 已提交
430
		disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
J
Johannes Rieken 已提交
431
			provideHover(): any {
B
Benjamin Pasero 已提交
432
				return new types.Hover('Hello');
J
Johannes Rieken 已提交
433 434 435
			}
		}));

M
Matt Bierner 已提交
436 437 438
		await rpcProtocol.sync();
		getHover(model, new EditorPosition(1, 1), CancellationToken.None).then(value => {
			assert.equal(value.length, 1);
439 440 441 442 443
		});
	});

	// --- occurrences

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

M
Matt Bierner 已提交
446
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
447
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
448
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
449 450 451
			}
		}));

M
Matt Bierner 已提交
452
		await rpcProtocol.sync();
453
		const value = (await getOccurrencesAtPosition(model, new EditorPosition(1, 2), CancellationToken.None))!;
M
Matt Bierner 已提交
454
		assert.equal(value.length, 1);
455
		const [entry] = value;
M
Matt Bierner 已提交
456 457
		assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 });
		assert.equal(entry.kind, modes.DocumentHighlightKind.Text);
458 459
	});

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

M
Matt Bierner 已提交
462
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
463
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
464
				return [];
465 466
			}
		}));
M
Matt Bierner 已提交
467
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, '*', new class implements vscode.DocumentHighlightProvider {
468
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
469
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
470 471 472
			}
		}));

M
Matt Bierner 已提交
473
		await rpcProtocol.sync();
474
		const value = (await getOccurrencesAtPosition(model, new EditorPosition(1, 2), CancellationToken.None))!;
M
Matt Bierner 已提交
475
		assert.equal(value.length, 1);
476
		const [entry] = value;
M
Matt Bierner 已提交
477 478
		assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 });
		assert.equal(entry.kind, modes.DocumentHighlightKind.Text);
479 480
	});

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

M
Matt Bierner 已提交
483
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
484
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
485
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 2))];
486 487
			}
		}));
M
Matt Bierner 已提交
488
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, '*', new class implements vscode.DocumentHighlightProvider {
489
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
490
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
491 492 493
			}
		}));

M
Matt Bierner 已提交
494
		await rpcProtocol.sync();
495
		const value = (await getOccurrencesAtPosition(model, new EditorPosition(1, 2), CancellationToken.None))!;
M
Matt Bierner 已提交
496
		assert.equal(value.length, 1);
497
		const [entry] = value;
M
Matt Bierner 已提交
498 499
		assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 3 });
		assert.equal(entry.kind, modes.DocumentHighlightKind.Text);
500 501
	});

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

M
Matt Bierner 已提交
504
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
505 506 507 508 509
			provideDocumentHighlights(): any {
				throw new Error('evil');
			}
		}));

M
Matt Bierner 已提交
510
		disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
511
			provideDocumentHighlights(): any {
B
Benjamin Pasero 已提交
512
				return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
513 514 515
			}
		}));

M
Matt Bierner 已提交
516 517
		await rpcProtocol.sync();
		const value = await getOccurrencesAtPosition(model, new EditorPosition(1, 2), CancellationToken.None);
518
		assert.equal(value!.length, 1);
J
Johannes Rieken 已提交
519
	});
J
Johannes Rieken 已提交
520 521 522

	// --- references

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

M
Matt Bierner 已提交
525
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
J
Johannes Rieken 已提交
526 527 528 529 530
			provideReferences(): any {
				return [new types.Location(URI.parse('far://register/first'), new types.Range(0, 0, 0, 0))];
			}
		}));

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

M
Matt Bierner 已提交
537 538 539 540 541 542
		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 已提交
543 544
	});

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

M
Matt Bierner 已提交
547
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
J
Johannes Rieken 已提交
548
			provideReferences(): any {
549
				return [new types.Location(model.uri, new types.Position(0, 0))];
J
Johannes Rieken 已提交
550 551 552
			}
		}));

M
Matt Bierner 已提交
553 554 555 556 557 558
		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 已提交
559 560
	});

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

M
Matt Bierner 已提交
563
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
J
Johannes Rieken 已提交
564 565 566 567
			provideReferences(): any {
				throw new Error('evil');
			}
		}));
M
Matt Bierner 已提交
568
		disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
J
Johannes Rieken 已提交
569
			provideReferences(): any {
570
				return [new types.Location(model.uri, new types.Range(0, 0, 0, 0))];
J
Johannes Rieken 已提交
571 572 573
			}
		}));

M
Matt Bierner 已提交
574 575 576
		await rpcProtocol.sync();
		const value = await provideReferences(model, new EditorPosition(1, 2), CancellationToken.None);
		assert.equal(value.length, 1);
J
Johannes Rieken 已提交
577
	});
J
Johannes Rieken 已提交
578 579 580

	// --- quick fix

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

583
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, {
584
			provideCodeActions(): vscode.Command[] {
J
Johannes Rieken 已提交
585
				return [
586 587
					{ command: 'test1', title: 'Testing1' },
					{ command: 'test2', title: 'Testing2' }
J
Johannes Rieken 已提交
588 589 590 591
				];
			}
		}));

M
Matt Bierner 已提交
592
		await rpcProtocol.sync();
M
Matt Bierner 已提交
593 594 595
		const { actions } = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
		assert.equal(actions.length, 2);
		const [first, second] = actions;
M
Matt Bierner 已提交
596
		assert.equal(first.title, 'Testing1');
597
		assert.equal(first.command!.id, 'test1');
M
Matt Bierner 已提交
598
		assert.equal(second.title, 'Testing2');
599
		assert.equal(second.command!.id, 'test2');
J
Johannes Rieken 已提交
600 601
	});

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

604
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, {
M
Matt Bierner 已提交
605 606 607 608 609 610 611 612 613 614 615
			provideCodeActions(): vscode.CodeAction[] {
				return [
					{
						title: 'Testing1',
						command: { title: 'Testing1Command', command: 'test1' },
						kind: types.CodeActionKind.Empty.append('test.scope')
					}
				];
			}
		}));

M
Matt Bierner 已提交
616
		await rpcProtocol.sync();
M
Matt Bierner 已提交
617 618 619
		const { actions } = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
		assert.equal(actions.length, 1);
		const [first] = actions;
M
Matt Bierner 已提交
620
		assert.equal(first.title, 'Testing1');
621 622
		assert.equal(first.command!.title, 'Testing1Command');
		assert.equal(first.command!.id, 'test1');
M
Matt Bierner 已提交
623
		assert.equal(first.kind, 'test.scope');
M
Matt Bierner 已提交
624 625 626
	});


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

M
Matt Bierner 已提交
629
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
J
Johannes Rieken 已提交
630 631 632 633
			provideCodeActions(): any {
				return [
					undefined,
					null,
M
Matt Bierner 已提交
634
					{ command: 'test', title: 'Testing' }
J
Johannes Rieken 已提交
635 636 637 638
				];
			}
		}));

M
Matt Bierner 已提交
639
		await rpcProtocol.sync();
M
Matt Bierner 已提交
640 641
		const { actions } = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
		assert.equal(actions.length, 1);
J
Johannes Rieken 已提交
642 643
	});

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

M
Matt Bierner 已提交
646
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
J
Johannes Rieken 已提交
647 648 649 650
			provideCodeActions(): any {
				throw new Error('evil');
			}
		}));
M
Matt Bierner 已提交
651
		disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
J
Johannes Rieken 已提交
652
			provideCodeActions(): any {
M
Matt Bierner 已提交
653
				return [{ command: 'test', title: 'Testing' }];
J
Johannes Rieken 已提交
654 655 656
			}
		}));

M
Matt Bierner 已提交
657
		await rpcProtocol.sync();
M
Matt Bierner 已提交
658 659
		const { actions } = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
		assert.equal(actions.length, 1);
J
Johannes Rieken 已提交
660
	});
661 662 663

	// --- navigate types

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

M
Matt Bierner 已提交
666
		disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
667 668 669 670 671
			provideWorkspaceSymbols(): any {
				throw new Error('evil');
			}
		}));

M
Matt Bierner 已提交
672
		disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
673
			provideWorkspaceSymbols(): any {
B
Benjamin Pasero 已提交
674
				return [new types.SymbolInformation('testing', types.SymbolKind.Array, new types.Range(0, 0, 1, 1))];
675 676 677
			}
		}));

M
Matt Bierner 已提交
678 679 680 681 682 683 684
		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 已提交
685 686 687 688
	});

	// --- rename

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

M
Matt Bierner 已提交
691
		disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
692
			provideRenameEdits(): any {
J
Johannes Rieken 已提交
693
				throw new class Foo { };
J
Johannes Rieken 已提交
694 695 696
			}
		}));

M
Matt Bierner 已提交
697 698 699 700 701 702 703 704
		await rpcProtocol.sync();
		try {
			await rename(model, new EditorPosition(1, 1), 'newName');
			throw Error();
		}
		catch (err) {
			// expected
		}
J
Johannes Rieken 已提交
705 706
	});

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

M
Matt Bierner 已提交
709
		disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
710 711 712 713 714
			provideRenameEdits(): any {
				throw Error('evil');
			}
		}));

M
Matt Bierner 已提交
715 716 717
		await rpcProtocol.sync();
		const value = await rename(model, new EditorPosition(1, 1), 'newName');
		assert.equal(value.rejectReason, 'evil');
J
Johannes Rieken 已提交
718 719
	});

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

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

M
Matt Bierner 已提交
728
		disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
729 730
			provideRenameEdits(): any {
				let edit = new types.WorkspaceEdit();
731
				edit.replace(model.uri, new types.Range(0, 0, 0, 0), 'testing');
J
Johannes Rieken 已提交
732 733 734 735
				return edit;
			}
		}));

M
Matt Bierner 已提交
736 737 738
		await rpcProtocol.sync();
		const value = await rename(model, new EditorPosition(1, 1), 'newName');
		assert.equal(value.edits.length, 1);
J
Johannes Rieken 已提交
739 740
	});

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

M
Matt Bierner 已提交
743
		disposables.push(extHost.registerRenameProvider(defaultExtension, '*', new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
744 745
			provideRenameEdits(): any {
				let edit = new types.WorkspaceEdit();
746 747
				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 已提交
748 749 750 751
				return edit;
			}
		}));

M
Matt Bierner 已提交
752
		disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
J
Johannes Rieken 已提交
753 754 755 756 757
			provideRenameEdits(): any {
				return;
			}
		}));

M
Matt Bierner 已提交
758 759 760 761 762 763
		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 已提交
764
	});
765 766 767

	// --- parameter hints

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

M
Matt Bierner 已提交
770
		disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
J
Johannes Rieken 已提交
771 772 773 774 775
			provideSignatureHelp(): any {
				return undefined;
			}
		}, []));

M
Matt Bierner 已提交
776
		disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
J
Johannes Rieken 已提交
777
			provideSignatureHelp(): vscode.SignatureHelp {
778 779 780 781 782
				return {
					signatures: [],
					activeParameter: 0,
					activeSignature: 0
				};
J
Johannes Rieken 已提交
783 784 785
			}
		}, []));

M
Matt Bierner 已提交
786 787 788
		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 已提交
789
	});
790

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

M
Matt Bierner 已提交
793
		disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
794 795 796 797 798
			provideSignatureHelp(): any {
				throw new Error('evil');
			}
		}, []));

M
Matt Bierner 已提交
799 800 801
		await rpcProtocol.sync();
		const value = await provideSignatureHelp(model, new EditorPosition(1, 1), { triggerKind: modes.SignatureHelpTriggerKind.Invoke, isRetrigger: false }, CancellationToken.None);
		assert.equal(value, undefined);
802 803 804 805
	});

	// --- suggestions

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

M
Matt Bierner 已提交
808
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, '*', new class implements vscode.CompletionItemProvider {
809 810 811 812 813
			provideCompletionItems(): any {
				return [new types.CompletionItem('testing1')];
			}
		}, []));

M
Matt Bierner 已提交
814
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
815 816 817 818 819
			provideCompletionItems(): any {
				return [new types.CompletionItem('testing2')];
			}
		}, []));

M
Matt Bierner 已提交
820
		await rpcProtocol.sync();
821
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
M
Matt Bierner 已提交
822 823
		assert.equal(value.length, 1);
		assert.equal(value[0].completion.insertText, 'testing2');
824 825
	});

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

M
Matt Bierner 已提交
828
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, '*', new class implements vscode.CompletionItemProvider {
829 830 831 832 833
			provideCompletionItems(): any {
				return [new types.CompletionItem('weak-selector')]; // weaker selector but result
			}
		}, []));

M
Matt Bierner 已提交
834
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
835 836 837 838 839
			provideCompletionItems(): any {
				return []; // stronger selector but not a good result;
			}
		}, []));

M
Matt Bierner 已提交
840
		await rpcProtocol.sync();
841
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
M
Matt Bierner 已提交
842 843
		assert.equal(value.length, 1);
		assert.equal(value[0].completion.insertText, 'weak-selector');
B
Benjamin Pasero 已提交
844
	});
845

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

M
Matt Bierner 已提交
848
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
849 850 851 852 853
			provideCompletionItems(): any {
				return [new types.CompletionItem('strong-1')];
			}
		}, []));

M
Matt Bierner 已提交
854
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
855 856 857 858 859
			provideCompletionItems(): any {
				return [new types.CompletionItem('strong-2')];
			}
		}, []));

M
Matt Bierner 已提交
860
		await rpcProtocol.sync();
861
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
M
Matt Bierner 已提交
862 863 864
		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 已提交
865
	});
866

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

M
Matt Bierner 已提交
869
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
870 871 872 873 874
			provideCompletionItems(): any {
				throw new Error('evil');
			}
		}, []));

M
Matt Bierner 已提交
875
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
876 877 878 879 880 881
			provideCompletionItems(): any {
				return [new types.CompletionItem('testing')];
			}
		}, []));


M
Matt Bierner 已提交
882
		await rpcProtocol.sync();
883
		const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
M
Matt Bierner 已提交
884
		assert.equal(value[0].container.incomplete, undefined);
885
	});
886

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

M
Matt Bierner 已提交
889
		disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
890
			provideCompletionItems(): any {
J
Johannes Rieken 已提交
891
				return new types.CompletionList([<any>new types.CompletionItem('hello')], true);
892 893 894
			}
		}, []));

M
Matt Bierner 已提交
895
		await rpcProtocol.sync();
896
		provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet))).then(value => {
M
Matt Bierner 已提交
897
			assert.equal(value[0].container.incomplete, true);
898 899 900
		});
	});

901 902
	// --- format

J
Johannes Rieken 已提交
903
	const NullWorkerService = new class extends mock<IEditorWorkerService>() {
904
		computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[] | null | undefined): Promise<modes.TextEdit[] | undefined> {
905
			return Promise.resolve(withNullAsUndefined(edits));
J
Johannes Rieken 已提交
906 907 908
		}
	};

M
Matt Bierner 已提交
909
	test('Format Doc, data conversion', async () => {
M
Matt Bierner 已提交
910
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
911
			provideDocumentFormattingEdits(): any {
912
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing'), types.TextEdit.setEndOfLine(types.EndOfLine.LF)];
913 914 915
			}
		}));

M
Matt Bierner 已提交
916
		await rpcProtocol.sync();
917
		let value = (await getDocumentFormattingEditsUntilResult(NullWorkerService, model, { insertSpaces: true, tabSize: 4 }, CancellationToken.None))!;
M
Matt Bierner 已提交
918 919 920 921 922 923 924
		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 });
925 926
	});

M
Matt Bierner 已提交
927
	test('Format Doc, evil provider', async () => {
M
Matt Bierner 已提交
928
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
929 930 931 932 933
			provideDocumentFormattingEdits(): any {
				throw new Error('evil');
			}
		}));

M
Matt Bierner 已提交
934
		await rpcProtocol.sync();
935
		return getDocumentFormattingEditsUntilResult(NullWorkerService, model, { insertSpaces: true, tabSize: 4 }, CancellationToken.None);
936 937
	});

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

M
Matt Bierner 已提交
940
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
941 942 943 944 945
			provideDocumentFormattingEdits(): any {
				return undefined;
			}
		}));

M
Matt Bierner 已提交
946
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
947 948 949 950 951
			provideDocumentFormattingEdits(): any {
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')];
			}
		}));

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

M
Matt Bierner 已提交
958
		await rpcProtocol.sync();
959
		let value = (await getDocumentFormattingEditsUntilResult(NullWorkerService, model, { insertSpaces: true, tabSize: 4 }, CancellationToken.None))!;
M
Matt Bierner 已提交
960 961 962 963
		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 });
964 965
	});

M
Matt Bierner 已提交
966
	test('Format Range, data conversion', async () => {
M
Matt Bierner 已提交
967
		disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
968
			provideDocumentRangeFormattingEdits(): any {
J
Johannes Rieken 已提交
969
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')];
970 971 972
			}
		}));

M
Matt Bierner 已提交
973
		await rpcProtocol.sync();
974
		const value = (await getDocumentRangeFormattingEditsUntilResult(NullWorkerService, model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }, CancellationToken.None))!;
M
Matt Bierner 已提交
975
		assert.equal(value.length, 1);
976
		const [first] = value;
M
Matt Bierner 已提交
977 978
		assert.equal(first.text, 'testing');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
B
Benjamin Pasero 已提交
979
	});
980

M
Matt Bierner 已提交
981
	test('Format Range, + format_doc', async () => {
M
Matt Bierner 已提交
982
		disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
983
			provideDocumentRangeFormattingEdits(): any {
J
Johannes Rieken 已提交
984
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'range')];
985 986
			}
		}));
M
Matt Bierner 已提交
987
		disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
988 989 990 991
			provideDocumentRangeFormattingEdits(): any {
				return [new types.TextEdit(new types.Range(2, 3, 4, 5), 'range2')];
			}
		}));
M
Matt Bierner 已提交
992
		disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
993 994 995 996
			provideDocumentFormattingEdits(): any {
				return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'doc')];
			}
		}));
M
Matt Bierner 已提交
997
		await rpcProtocol.sync();
998
		const value = (await getDocumentRangeFormattingEditsUntilResult(NullWorkerService, model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }, CancellationToken.None))!;
M
Matt Bierner 已提交
999
		assert.equal(value.length, 1);
1000
		const [first] = value;
M
Matt Bierner 已提交
1001 1002 1003 1004 1005
		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);
1006 1007
	});

M
Matt Bierner 已提交
1008
	test('Format Range, evil provider', async () => {
M
Matt Bierner 已提交
1009
		disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
1010 1011 1012 1013 1014
			provideDocumentRangeFormattingEdits(): any {
				throw new Error('evil');
			}
		}));

M
Matt Bierner 已提交
1015
		await rpcProtocol.sync();
1016
		return getDocumentRangeFormattingEditsUntilResult(NullWorkerService, model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }, CancellationToken.None);
B
Benjamin Pasero 已提交
1017
	});
1018

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

M
Matt Bierner 已提交
1021
		disposables.push(extHost.registerOnTypeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.OnTypeFormattingEditProvider {
1022 1023 1024 1025 1026
			provideOnTypeFormattingEdits(): any {
				return [new types.TextEdit(new types.Range(0, 0, 0, 0), arguments[2])];
			}
		}, [';']));

M
Matt Bierner 已提交
1027
		await rpcProtocol.sync();
1028
		const value = (await getOnTypeFormattingEdits(NullWorkerService, model, new EditorPosition(1, 1), ';', { insertSpaces: true, tabSize: 2 }))!;
M
Matt Bierner 已提交
1029
		assert.equal(value.length, 1);
1030
		const [first] = value;
M
Matt Bierner 已提交
1031 1032
		assert.equal(first.text, ';');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
1033
	});
J
Johannes Rieken 已提交
1034

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

M
Matt Bierner 已提交
1037
		disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
J
Johannes Rieken 已提交
1038
			provideDocumentLinks() {
1039 1040 1041
				const link = new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'));
				link.tooltip = 'tooltip';
				return [link];
J
Johannes Rieken 已提交
1042 1043 1044
			}
		}));

M
Matt Bierner 已提交
1045
		await rpcProtocol.sync();
1046 1047 1048
		let { links } = await getLinks(model, CancellationToken.None);
		assert.equal(links.length, 1);
		let [first] = links;
M
Matt Bierner 已提交
1049 1050
		assert.equal(first.url, 'foo:bar#3');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 });
1051
		assert.equal(first.tooltip, 'tooltip');
J
Johannes Rieken 已提交
1052 1053
	});

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

M
Matt Bierner 已提交
1056
		disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
J
Johannes Rieken 已提交
1057
			provideDocumentLinks() {
1058
				return [new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'))];
J
Johannes Rieken 已提交
1059 1060 1061
			}
		}));

M
Matt Bierner 已提交
1062
		disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
J
Johannes Rieken 已提交
1063 1064 1065 1066 1067
			provideDocumentLinks(): any {
				throw new Error();
			}
		}));

M
Matt Bierner 已提交
1068
		await rpcProtocol.sync();
1069 1070 1071
		let { links } = await getLinks(model, CancellationToken.None);
		assert.equal(links.length, 1);
		let [first] = links;
M
Matt Bierner 已提交
1072 1073
		assert.equal(first.url, 'foo:bar#3');
		assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 });
J
Johannes Rieken 已提交
1074
	});
1075

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

M
Matt Bierner 已提交
1078
		disposables.push(extHost.registerColorProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentColorProvider {
1079 1080
			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 已提交
1081
			}
1082 1083 1084 1085 1086
			provideColorPresentations(color: vscode.Color, context: { range: vscode.Range, document: vscode.TextDocument }): vscode.ColorPresentation[] {
				return [];
			}
		}));

M
Matt Bierner 已提交
1087 1088 1089 1090 1091 1092
		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 });
1093
	});
1094 1095 1096

	// -- selection ranges

M
Matt Bierner 已提交
1097
	test('Selection Ranges, data conversion', async () => {
M
Matt Bierner 已提交
1098
		disposables.push(extHost.registerSelectionRangeProvider(defaultExtension, defaultSelector, new class implements vscode.SelectionRangeProvider {
1099
			provideSelectionRanges() {
1100 1101 1102
				return [
					new types.SelectionRange(new types.Range(0, 10, 0, 18), new types.SelectionRange(new types.Range(0, 2, 0, 20))),
				];
1103 1104 1105 1106 1107
			}
		}));

		await rpcProtocol.sync();

1108 1109 1110
		provideSelectionRanges(model, [new Position(1, 17)], CancellationToken.None).then(ranges => {
			assert.equal(ranges.length, 1);
			assert.ok(ranges[0].length >= 2);
1111 1112
		});
	});
1113 1114 1115

	test('Selection Ranges, bad data', async () => {

1116 1117 1118 1119 1120 1121 1122 1123
		try {
			let _a = new types.SelectionRange(new types.Range(0, 10, 0, 18),
				new types.SelectionRange(new types.Range(0, 11, 0, 18))
			);
			assert.ok(false, String(_a));
		} catch (err) {
			assert.ok(true);
		}
1124 1125

	});
J
tslint  
Johannes Rieken 已提交
1126
});