extHostLanguageFeatures.ts 38.0 KB
Newer Older
J
Johannes Rieken 已提交
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

import URI from 'vs/base/common/uri';
J
Johannes Rieken 已提交
8
import { TPromise } from 'vs/base/common/winjs.base';
9
import { mixin } from 'vs/base/common/objects';
J
Johannes Rieken 已提交
10
import * as vscode from 'vscode';
J
Johannes Rieken 已提交
11
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
12
import { Range, Disposable, CompletionList, SnippetString } from 'vs/workbench/api/node/extHostTypes';
A
Alex Dima 已提交
13
import { ISingleEditOperation } from 'vs/editor/common/editorCommon';
J
Johannes Rieken 已提交
14
import * as modes from 'vs/editor/common/modes';
J
Johannes Rieken 已提交
15 16
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
17
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
J
Johannes Rieken 已提交
18
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
19
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
20
import { asWinJsPromise } from 'vs/base/common/async';
21
import { MainContext, MainThreadTelemetryShape, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion } from './extHost.protocol';
J
Johannes Rieken 已提交
22
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
23 24
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
25 26 27
import { containsCommandLink } from 'vs/base/common/htmlContent';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { once } from 'vs/base/common/functional';
J
Johannes Rieken 已提交
28 29 30

// --- adapter

31
class OutlineAdapter {
J
Johannes Rieken 已提交
32

33
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
34 35
	private _provider: vscode.DocumentSymbolProvider;

36
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentSymbolProvider) {
J
Johannes Rieken 已提交
37 38 39 40
		this._documents = documents;
		this._provider = provider;
	}

41
	provideDocumentSymbols(resource: URI): TPromise<modes.SymbolInformation[]> {
42
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
43 44
		return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => {
			if (Array.isArray(value)) {
45
				return value.map(TypeConverters.fromSymbolInformation);
J
Johannes Rieken 已提交
46
			}
M
Matt Bierner 已提交
47
			return undefined;
J
Johannes Rieken 已提交
48 49 50 51
		});
	}
}

52
class CodeLensAdapter {
53

54 55
	private static _badCmd: vscode.Command = { command: 'missing', title: '<<MISSING COMMAND>>' };

56
	private _documents: ExtHostDocuments;
57 58
	private _commands: CommandsConverter;
	private _heapService: ExtHostHeapService;
59 60
	private _provider: vscode.CodeLensProvider;

61
	constructor(documents: ExtHostDocuments, commands: CommandsConverter, heapService: ExtHostHeapService, provider: vscode.CodeLensProvider) {
62
		this._documents = documents;
63
		this._commands = commands;
64
		this._heapService = heapService;
65 66 67
		this._provider = provider;
	}

68
	provideCodeLenses(resource: URI): TPromise<modes.ICodeLensSymbol[]> {
69
		const doc = this._documents.getDocumentData(resource).document;
70

71 72 73 74 75 76 77 78
		return asWinJsPromise(token => this._provider.provideCodeLenses(doc, token)).then(lenses => {
			if (Array.isArray(lenses)) {
				return lenses.map(lens => {
					const id = this._heapService.keep(lens);
					return ObjectIdentifier.mixin({
						range: TypeConverters.fromRange(lens.range),
						command: this._commands.toInternal(lens.command)
					}, id);
79 80
				});
			}
M
Matt Bierner 已提交
81
			return undefined;
82
		});
83 84
	}

85
	resolveCodeLens(resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
86

87 88
		const lens = this._heapService.get<vscode.CodeLens>(ObjectIdentifier.of(symbol));
		if (!lens) {
M
Matt Bierner 已提交
89
			return undefined;
90 91
		}

92 93 94 95 96 97
		let resolve: TPromise<vscode.CodeLens>;
		if (typeof this._provider.resolveCodeLens !== 'function' || lens.isResolved) {
			resolve = TPromise.as(lens);
		} else {
			resolve = asWinJsPromise(token => this._provider.resolveCodeLens(lens, token));
		}
98

99 100 101 102
		return resolve.then(newLens => {
			newLens = newLens || lens;
			symbol.command = this._commands.toInternal(newLens.command || CodeLensAdapter._badCmd);
			return symbol;
103 104 105 106
		});
	}
}

107
class DefinitionAdapter {
108
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
109 110
	private _provider: vscode.DefinitionProvider;

111
	constructor(documents: ExtHostDocuments, provider: vscode.DefinitionProvider) {
J
Johannes Rieken 已提交
112 113 114 115
		this._documents = documents;
		this._provider = provider;
	}

116
	provideDefinition(resource: URI, position: IPosition): TPromise<modes.Definition> {
117
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
118 119 120
		let pos = TypeConverters.toPosition(position);
		return asWinJsPromise(token => this._provider.provideDefinition(doc, pos, token)).then(value => {
			if (Array.isArray(value)) {
J
Johannes Rieken 已提交
121
				return value.map(TypeConverters.location.from);
J
Johannes Rieken 已提交
122
			} else if (value) {
J
Johannes Rieken 已提交
123
				return TypeConverters.location.from(value);
J
Johannes Rieken 已提交
124
			}
M
Matt Bierner 已提交
125
			return undefined;
J
Johannes Rieken 已提交
126 127 128 129
		});
	}
}

130 131
class ImplementationAdapter {
	private _documents: ExtHostDocuments;
M
Matt Bierner 已提交
132
	private _provider: vscode.ImplementationProvider;
133

M
Matt Bierner 已提交
134
	constructor(documents: ExtHostDocuments, provider: vscode.ImplementationProvider) {
135 136 137 138
		this._documents = documents;
		this._provider = provider;
	}

M
Matt Bierner 已提交
139
	provideImplementation(resource: URI, position: IPosition): TPromise<modes.Definition> {
140 141
		let doc = this._documents.getDocumentData(resource).document;
		let pos = TypeConverters.toPosition(position);
M
Matt Bierner 已提交
142
		return asWinJsPromise(token => this._provider.provideImplementation(doc, pos, token)).then(value => {
143 144 145 146 147
			if (Array.isArray(value)) {
				return value.map(TypeConverters.location.from);
			} else if (value) {
				return TypeConverters.location.from(value);
			}
M
Matt Bierner 已提交
148
			return undefined;
149 150 151 152
		});
	}
}

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
class TypeDefinitionAdapter {
	private _documents: ExtHostDocuments;
	private _provider: vscode.TypeDefinitionProvider;

	constructor(documents: ExtHostDocuments, provider: vscode.TypeDefinitionProvider) {
		this._documents = documents;
		this._provider = provider;
	}

	provideTypeDefinition(resource: URI, position: IPosition): TPromise<modes.Definition> {
		const doc = this._documents.getDocumentData(resource).document;
		const pos = TypeConverters.toPosition(position);
		return asWinJsPromise(token => this._provider.provideTypeDefinition(doc, pos, token)).then(value => {
			if (Array.isArray(value)) {
				return value.map(TypeConverters.location.from);
			} else if (value) {
				return TypeConverters.location.from(value);
			}
			return undefined;
		});
	}
}


177
class HoverAdapter {
J
Johannes Rieken 已提交
178

179 180 181 182 183 184
	constructor(
		private readonly _documents: ExtHostDocuments,
		private readonly _provider: vscode.HoverProvider,
		private readonly _telemetryLog: (name: string, data: object) => void,
	) {
		//
J
Johannes Rieken 已提交
185 186
	}

187
	public provideHover(resource: URI, position: IPosition): TPromise<modes.Hover> {
J
Johannes Rieken 已提交
188

189
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
190 191 192
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideHover(doc, pos, token)).then(value => {
193
			if (!value || isFalsyOrEmpty(value.contents)) {
M
Matt Bierner 已提交
194
				return undefined;
J
Johannes Rieken 已提交
195
			}
196 197
			if (!value.range) {
				value.range = doc.getWordRangeAtPosition(pos);
J
Johannes Rieken 已提交
198
			}
199 200
			if (!value.range) {
				value.range = new Range(pos, pos);
J
Johannes Rieken 已提交
201 202
			}

203 204 205 206
			const result = TypeConverters.fromHover(value);

			// we wanna know which extension uses command links
			// because that is a potential trick-attack on users
207
			if (result.contents.some(h => containsCommandLink(h.value))) {
208
				this._telemetryLog('usesCommandLink', { from: 'hover' });
209 210
			}
			return result;
J
Johannes Rieken 已提交
211 212 213 214
		});
	}
}

215
class DocumentHighlightAdapter {
216

217
	private _documents: ExtHostDocuments;
218 219
	private _provider: vscode.DocumentHighlightProvider;

220
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentHighlightProvider) {
221 222 223 224
		this._documents = documents;
		this._provider = provider;
	}

225
	provideDocumentHighlights(resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]> {
226

227
		let doc = this._documents.getDocumentData(resource).document;
228 229 230 231
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => {
			if (Array.isArray(value)) {
232
				return value.map(DocumentHighlightAdapter._convertDocumentHighlight);
233
			}
M
Matt Bierner 已提交
234
			return undefined;
235 236 237
		});
	}

238
	private static _convertDocumentHighlight(documentHighlight: vscode.DocumentHighlight): modes.DocumentHighlight {
239 240
		return {
			range: TypeConverters.fromRange(documentHighlight.range),
241
			kind: documentHighlight.kind
B
Benjamin Pasero 已提交
242
		};
243 244 245
	}
}

246
class ReferenceAdapter {
J
Johannes Rieken 已提交
247

248
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
249 250
	private _provider: vscode.ReferenceProvider;

251
	constructor(documents: ExtHostDocuments, provider: vscode.ReferenceProvider) {
J
Johannes Rieken 已提交
252 253 254 255
		this._documents = documents;
		this._provider = provider;
	}

256
	provideReferences(resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]> {
257
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
258 259
		let pos = TypeConverters.toPosition(position);

260
		return asWinJsPromise(token => this._provider.provideReferences(doc, pos, context, token)).then(value => {
J
Johannes Rieken 已提交
261
			if (Array.isArray(value)) {
J
Johannes Rieken 已提交
262
				return value.map(TypeConverters.location.from);
J
Johannes Rieken 已提交
263
			}
M
Matt Bierner 已提交
264
			return undefined;
J
Johannes Rieken 已提交
265 266 267 268
		});
	}
}

269
class QuickFixAdapter {
J
Johannes Rieken 已提交
270

271
	private _documents: ExtHostDocuments;
272
	private _commands: CommandsConverter;
273
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
274 275
	private _provider: vscode.CodeActionProvider;

J
Johannes Rieken 已提交
276
	constructor(documents: ExtHostDocuments, commands: CommandsConverter, diagnostics: ExtHostDiagnostics, provider: vscode.CodeActionProvider) {
J
Johannes Rieken 已提交
277 278
		this._documents = documents;
		this._commands = commands;
279
		this._diagnostics = diagnostics;
J
Johannes Rieken 已提交
280 281 282
		this._provider = provider;
	}

J
Johannes Rieken 已提交
283
	provideCodeActions(resource: URI, range: IRange): TPromise<modes.Command[]> {
J
Johannes Rieken 已提交
284

285
		const doc = this._documents.getDocumentData(resource).document;
286
		const ran = <vscode.Range>TypeConverters.toRange(range);
287 288 289 290 291
		const allDiagnostics: vscode.Diagnostic[] = [];

		this._diagnostics.forEach(collection => {
			if (collection.has(resource)) {
				for (let diagnostic of collection.get(resource)) {
292
					if (ran.contains(diagnostic.range)) {
293 294 295 296
						allDiagnostics.push(diagnostic);
					}
				}
			}
J
Johannes Rieken 已提交
297 298
		});

299
		return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)).then(commands => {
J
Johannes Rieken 已提交
300
			if (!Array.isArray(commands)) {
M
Matt Bierner 已提交
301
				return undefined;
J
Johannes Rieken 已提交
302
			}
J
Johannes Rieken 已提交
303
			return commands.map(command => this._commands.toInternal(command));
J
Johannes Rieken 已提交
304 305 306 307
		});
	}
}

308
class DocumentFormattingAdapter {
309

310
	private _documents: ExtHostDocuments;
311 312
	private _provider: vscode.DocumentFormattingEditProvider;

313
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentFormattingEditProvider) {
314 315 316 317
		this._documents = documents;
		this._provider = provider;
	}

A
Alex Dima 已提交
318
	provideDocumentFormattingEdits(resource: URI, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
319

320
		const { document } = this._documents.getDocumentData(resource);
321 322

		return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(document, <any>options, token)).then(value => {
323
			if (Array.isArray(value)) {
324
				return value.map(TypeConverters.TextEdit.from);
325
			}
M
Matt Bierner 已提交
326
			return undefined;
327 328 329 330
		});
	}
}

331
class RangeFormattingAdapter {
332

333
	private _documents: ExtHostDocuments;
334 335
	private _provider: vscode.DocumentRangeFormattingEditProvider;

336
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentRangeFormattingEditProvider) {
337 338 339 340
		this._documents = documents;
		this._provider = provider;
	}

A
Alex Dima 已提交
341
	provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
342

343
		const { document } = this._documents.getDocumentData(resource);
344
		const ran = TypeConverters.toRange(range);
345

346
		return asWinJsPromise(token => this._provider.provideDocumentRangeFormattingEdits(document, ran, <any>options, token)).then(value => {
347
			if (Array.isArray(value)) {
348
				return value.map(TypeConverters.TextEdit.from);
349
			}
M
Matt Bierner 已提交
350
			return undefined;
351 352 353 354
		});
	}
}

355
class OnTypeFormattingAdapter {
356

357
	private _documents: ExtHostDocuments;
358 359
	private _provider: vscode.OnTypeFormattingEditProvider;

360
	constructor(documents: ExtHostDocuments, provider: vscode.OnTypeFormattingEditProvider) {
361 362 363 364
		this._documents = documents;
		this._provider = provider;
	}

365
	autoFormatTriggerCharacters: string[] = []; // not here
366

A
Alex Dima 已提交
367
	provideOnTypeFormattingEdits(resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
368

369
		const { document } = this._documents.getDocumentData(resource);
370
		const pos = TypeConverters.toPosition(position);
371

J
Johannes Rieken 已提交
372
		return asWinJsPromise(token => this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token)).then(value => {
373
			if (Array.isArray(value)) {
374
				return value.map(TypeConverters.TextEdit.from);
375
			}
M
Matt Bierner 已提交
376
			return undefined;
377 378 379 380
		});
	}
}

381

382
class NavigateTypeAdapter implements IWorkspaceSymbolProvider {
383 384

	private _provider: vscode.WorkspaceSymbolProvider;
385
	private _heapService: ExtHostHeapService;
386

387
	constructor(provider: vscode.WorkspaceSymbolProvider, heapService: ExtHostHeapService) {
388
		this._provider = provider;
389
		this._heapService = heapService;
390 391
	}

392
	provideWorkspaceSymbols(search: string): TPromise<modes.SymbolInformation[]> {
393

394 395
		return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
			if (Array.isArray(value)) {
396 397 398 399
				return value.map(item => {
					const id = this._heapService.keep(item);
					const result = TypeConverters.fromSymbolInformation(item);
					return ObjectIdentifier.mixin(result, id);
400
				});
401
			}
M
Matt Bierner 已提交
402
			return undefined;
403 404
		});
	}
405

406
	resolveWorkspaceSymbol(item: modes.SymbolInformation): TPromise<modes.SymbolInformation> {
407 408

		if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
409
			return TPromise.as(item);
410 411
		}

412
		const symbolInfo = this._heapService.get<vscode.SymbolInformation>(ObjectIdentifier.of(item));
413 414 415 416
		if (symbolInfo) {
			return asWinJsPromise(token => this._provider.resolveWorkspaceSymbol(symbolInfo, token)).then(value => {
				return value && TypeConverters.fromSymbolInformation(value);
			});
417
		}
M
Matt Bierner 已提交
418
		return undefined;
419
	}
420 421
}

422
class RenameAdapter {
J
Johannes Rieken 已提交
423

424
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
425 426
	private _provider: vscode.RenameProvider;

427
	constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) {
J
Johannes Rieken 已提交
428 429 430 431
		this._documents = documents;
		this._provider = provider;
	}

432
	provideRenameEdits(resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit> {
J
Johannes Rieken 已提交
433

434
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
435 436 437 438
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {
			if (!value) {
M
Matt Bierner 已提交
439
				return undefined;
J
Johannes Rieken 已提交
440 441
			}

442
			let result = <modes.WorkspaceEdit>{
J
Johannes Rieken 已提交
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
				edits: []
			};

			for (let entry of value.entries()) {
				let [uri, textEdits] = entry;
				for (let textEdit of textEdits) {
					result.edits.push({
						resource: <URI>uri,
						newText: textEdit.newText,
						range: TypeConverters.fromRange(textEdit.range)
					});
				}
			}
			return result;
		}, err => {
			if (typeof err === 'string') {
459
				return <modes.WorkspaceEdit>{
J
Johannes Rieken 已提交
460 461 462 463
					edits: undefined,
					rejectReason: err
				};
			}
464
			return TPromise.wrapError<modes.WorkspaceEdit>(err);
J
Johannes Rieken 已提交
465 466 467 468
		});
	}
}

469

470
class SuggestAdapter {
471

472 473 474 475
	static supportsResolving(provider: vscode.CompletionItemProvider): boolean {
		return typeof provider.resolveCompletionItem === 'function';
	}

476
	private _documents: ExtHostDocuments;
477
	private _commands: CommandsConverter;
478 479
	private _provider: vscode.CompletionItemProvider;

480 481 482 483
	private _cache = new Map<number, vscode.CompletionItem[]>();
	private _idPool = 0;

	constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) {
484
		this._documents = documents;
485
		this._commands = commands;
486 487 488
		this._provider = provider;
	}

489
	provideCompletionItems(resource: URI, position: IPosition): TPromise<IExtHostSuggestResult> {
490

491
		const doc = this._documents.getDocumentData(resource).document;
492 493
		const pos = TypeConverters.toPosition(position);

J
Johannes Rieken 已提交
494
		return asWinJsPromise<vscode.CompletionItem[] | vscode.CompletionList>(token => this._provider.provideCompletionItems(doc, pos, token)).then(value => {
495

496 497 498 499
			const _id = this._idPool++;

			const result: IExtHostSuggestResult = {
				_id,
500 501
				suggestions: [],
			};
502

503
			let list: CompletionList;
504
			if (!value) {
505
				// undefined and null are valid results
M
Matt Bierner 已提交
506
				return undefined;
507 508 509 510

			} else if (Array.isArray(value)) {
				list = new CompletionList(value);

511
			} else {
512 513
				list = value;
				result.incomplete = list.isIncomplete;
514
			}
515

516 517 518
			// the default text edit range
			const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos))
				.with({ end: pos });
519

520 521 522 523 524 525
			for (let i = 0; i < list.items.length; i++) {
				const suggestion = this._convertCompletionItem(list.items[i], pos, wordRangeBeforePos, i, _id);
				// check for bad completion item
				// for the converter did warn
				if (suggestion) {
					result.suggestions.push(suggestion);
526 527
				}
			}
528
			this._cache.set(_id, list.items);
529

530
			return result;
531 532 533
		});
	}

534
	resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
535 536

		if (typeof this._provider.resolveCompletionItem !== 'function') {
537 538
			return TPromise.as(suggestion);
		}
539

540 541
		const { _parentId, _id } = (<IExtHostSuggestion>suggestion);
		const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id];
542 543 544
		if (!item) {
			return TPromise.as(suggestion);
		}
545

546
		return asWinJsPromise(token => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
547 548 549 550 551 552 553 554

			if (!resolvedItem) {
				return suggestion;
			}

			const doc = this._documents.getDocumentData(resource).document;
			const pos = TypeConverters.toPosition(position);
			const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos)).with({ end: pos });
555
			const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
556 557 558 559
			if (newSuggestion) {
				mixin(suggestion, newSuggestion, true);
			}

560
			return suggestion;
561 562
		});
	}
563

564 565 566 567 568
	releaseCompletionItems(id: number): any {
		this._cache.delete(id);
	}

	private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): IExtHostSuggestion {
J
Johannes Rieken 已提交
569
		if (typeof item.label !== 'string' || item.label.length === 0) {
570
			console.warn('INVALID text edit -> must have at least a label');
M
Matt Bierner 已提交
571
			return undefined;
572 573
		}

574 575 576 577
		const result: IExtHostSuggestion = {
			//
			_id,
			_parentId,
578 579 580 581 582 583 584 585 586 587
			//
			label: item.label,
			type: TypeConverters.CompletionItemKind.from(item.kind),
			detail: item.detail,
			documentation: item.documentation,
			filterText: item.filterText,
			sortText: item.sortText,
			//
			insertText: undefined,
			additionalTextEdits: item.additionalTextEdits && item.additionalTextEdits.map(TypeConverters.TextEdit.from),
588 589
			command: this._commands.toInternal(item.command),
			commitCharacters: item.commitCharacters
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
		};

		// 'insertText'-logic
		if (item.textEdit) {
			result.insertText = item.textEdit.newText;
			result.snippetType = 'internal';

		} else if (typeof item.insertText === 'string') {
			result.insertText = item.insertText;
			result.snippetType = 'internal';

		} else if (item.insertText instanceof SnippetString) {
			result.insertText = item.insertText.value;
			result.snippetType = 'textmate';

		} else {
			result.insertText = item.label;
			result.snippetType = 'internal';
		}

		// 'overwrite[Before|After]'-logic
		let range: vscode.Range;
		if (item.textEdit) {
			range = item.textEdit.range;
		} else if (item.range) {
			range = item.range;
		} else {
			range = defaultRange;
		}
		result.overwriteBefore = position.character - range.start.character;
		result.overwriteAfter = range.end.character - position.character;

		if (!range.isSingleLine || range.start.line !== position.line) {
			console.warn('INVALID text edit -> must be single line and on the same line');
M
Matt Bierner 已提交
624
			return undefined;
625 626 627 628
		}

		return result;
	}
629 630
}

A
Alex Dima 已提交
631
class SignatureHelpAdapter {
632

633
	private _documents: ExtHostDocuments;
634 635
	private _provider: vscode.SignatureHelpProvider;

636
	constructor(documents: ExtHostDocuments, provider: vscode.SignatureHelpProvider) {
637 638 639 640
		this._documents = documents;
		this._provider = provider;
	}

641
	provideSignatureHelp(resource: URI, position: IPosition): TPromise<modes.SignatureHelp> {
642

643
		const doc = this._documents.getDocumentData(resource).document;
644 645 646
		const pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideSignatureHelp(doc, pos, token)).then(value => {
647
			if (value) {
648
				return TypeConverters.SignatureHelp.from(value);
649
			}
M
Matt Bierner 已提交
650
			return undefined;
651 652 653 654
		});
	}
}

J
Johannes Rieken 已提交
655 656 657
class LinkProviderAdapter {

	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
658
	private _heapService: ExtHostHeapService;
J
Johannes Rieken 已提交
659 660
	private _provider: vscode.DocumentLinkProvider;

J
Johannes Rieken 已提交
661
	constructor(documents: ExtHostDocuments, heapService: ExtHostHeapService, provider: vscode.DocumentLinkProvider) {
J
Johannes Rieken 已提交
662
		this._documents = documents;
J
Johannes Rieken 已提交
663
		this._heapService = heapService;
J
Johannes Rieken 已提交
664 665 666 667 668 669 670
		this._provider = provider;
	}

	provideLinks(resource: URI): TPromise<modes.ILink[]> {
		const doc = this._documents.getDocumentData(resource).document;

		return asWinJsPromise(token => this._provider.provideDocumentLinks(doc, token)).then(links => {
J
Johannes Rieken 已提交
671 672
			if (!Array.isArray(links)) {
				return undefined;
J
Johannes Rieken 已提交
673
			}
J
Johannes Rieken 已提交
674 675 676 677 678 679 680 681
			const result: modes.ILink[] = [];
			for (const link of links) {
				let data = TypeConverters.DocumentLink.from(link);
				let id = this._heapService.keep(link);
				ObjectIdentifier.mixin(data, id);
				result.push(data);
			}
			return result;
J
Johannes Rieken 已提交
682 683
		});
	}
684 685

	resolveLink(link: modes.ILink): TPromise<modes.ILink> {
J
Johannes Rieken 已提交
686 687
		if (typeof this._provider.resolveDocumentLink !== 'function') {
			return undefined;
688
		}
J
Johannes Rieken 已提交
689 690 691 692 693 694 695 696 697 698 699 700 701

		const id = ObjectIdentifier.of(link);
		const item = this._heapService.get<vscode.DocumentLink>(id);
		if (!item) {
			return undefined;
		}

		return asWinJsPromise(token => this._provider.resolveDocumentLink(item, token)).then(value => {
			if (value) {
				return TypeConverters.DocumentLink.from(value);
			}
			return undefined;
		});
702
	}
J
Johannes Rieken 已提交
703 704
}

705 706
class ColorProviderAdapter {

J
Joao Moreno 已提交
707 708 709 710 711 712
	constructor(
		private _proxy: MainThreadLanguageFeaturesShape,
		private _documents: ExtHostDocuments,
		private _colorFormatCache: Map<string, number>,
		private _provider: vscode.DocumentColorProvider
	) { }
713

714
	provideColors(resource: URI): TPromise<IRawColorInfo[]> {
715
		const doc = this._documents.getDocumentData(resource).document;
J
Joao Moreno 已提交
716 717 718
		return asWinJsPromise(token => this._provider.provideDocumentColors(doc, token)).then(colors => {
			if (!Array.isArray(colors)) {
				return [];
719 720
			}

J
Joao Moreno 已提交
721 722 723
			const colorInfos: IRawColorInfo[] = colors.map(ci => {
				return {
					color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] as [number, number, number, number],
724
					range: TypeConverters.fromRange(ci.range)
J
Joao Moreno 已提交
725 726 727 728
				};
			});

			return colorInfos;
729 730
		});
	}
731 732

	resolveColor(color: modes.IColor, colorFormat: modes.ColorFormat): TPromise<string> {
733
		return asWinJsPromise(token => this._provider.resolveDocumentColor(color, colorFormat));
734
	}
735 736
}

737
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
738
	| DocumentHighlightAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
739
	| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
740
	| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
J
Johannes Rieken 已提交
741

742
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
J
Johannes Rieken 已提交
743

744
	private static _handlePool: number = 0;
J
Johannes Rieken 已提交
745

746
	private _proxy: MainThreadLanguageFeaturesShape;
747
	private _telemetry: MainThreadTelemetryShape;
748
	private _documents: ExtHostDocuments;
749
	private _commands: ExtHostCommands;
750
	private _heapService: ExtHostHeapService;
751
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
752
	private _adapter = new Map<number, Adapter>();
J
Joao Moreno 已提交
753
	private _colorFormatCache = new Map<string, number>();
J
Johannes Rieken 已提交
754

755
	constructor(
756
		mainContext: IMainContext,
757
		documents: ExtHostDocuments,
758
		commands: ExtHostCommands,
J
Johannes Rieken 已提交
759
		heapMonitor: ExtHostHeapService,
760 761
		diagnostics: ExtHostDiagnostics
	) {
762
		this._proxy = mainContext.get(MainContext.MainThreadLanguageFeatures);
763
		this._telemetry = mainContext.get(MainContext.MainThreadTelemetry);
764 765
		this._documents = documents;
		this._commands = commands;
766
		this._heapService = heapMonitor;
767
		this._diagnostics = diagnostics;
J
Johannes Rieken 已提交
768 769 770 771
	}

	private _createDisposable(handle: number): Disposable {
		return new Disposable(() => {
J
Johannes Rieken 已提交
772
			this._adapter.delete(handle);
J
Johannes Rieken 已提交
773 774 775 776
			this._proxy.$unregister(handle);
		});
	}

777 778 779 780
	private _nextHandle(): number {
		return ExtHostLanguageFeatures._handlePool++;
	}

781
	private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => TPromise<R>): TPromise<R> {
J
Johannes Rieken 已提交
782
		let adapter = this._adapter.get(handle);
J
Johannes Rieken 已提交
783
		if (!(adapter instanceof ctor)) {
784
			return TPromise.wrapError<R>(new Error('no adapter found'));
J
Johannes Rieken 已提交
785
		}
J
Johannes Rieken 已提交
786
		return callback(<any>adapter);
787 788
	}

J
Johannes Rieken 已提交
789 790 791
	// --- outline

	registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
792
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
793
		this._adapter.set(handle, new OutlineAdapter(this._documents, provider));
794
		this._proxy.$registerOutlineSupport(handle, selector);
J
Johannes Rieken 已提交
795 796 797
		return this._createDisposable(handle);
	}

798 799
	$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]> {
		return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(resource));
J
Johannes Rieken 已提交
800
	}
801 802 803 804 805

	// --- code lens

	registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
		const handle = this._nextHandle();
806 807
		const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined;

J
Johannes Rieken 已提交
808
		this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider));
809 810 811 812 813 814 815 816 817
		this._proxy.$registerCodeLensSupport(handle, selector, eventHandle);
		let result = this._createDisposable(handle);

		if (eventHandle !== undefined) {
			const subscription = provider.onDidChangeCodeLenses(_ => this._proxy.$emitCodeLensEvent(eventHandle));
			result = Disposable.from(result, subscription);
		}

		return result;
818 819
	}

820 821
	$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(resource));
822 823
	}

824 825
	$resolveCodeLens(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(resource, symbol));
J
Johannes Rieken 已提交
826 827 828 829 830 831
	}

	// --- declaration

	registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
832
		this._adapter.set(handle, new DefinitionAdapter(this._documents, provider));
J
Johannes Rieken 已提交
833 834
		this._proxy.$registerDeclaractionSupport(handle, selector);
		return this._createDisposable(handle);
835 836
	}

837 838
	$provideDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
		return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(resource, position));
J
Johannes Rieken 已提交
839
	}
J
Johannes Rieken 已提交
840

M
Matt Bierner 已提交
841
	registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
842 843 844 845 846 847
		const handle = this._nextHandle();
		this._adapter.set(handle, new ImplementationAdapter(this._documents, provider));
		this._proxy.$registerImplementationSupport(handle, selector);
		return this._createDisposable(handle);
	}

M
Matt Bierner 已提交
848 849
	$provideImplementation(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
		return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(resource, position));
850 851
	}

852 853 854 855 856 857 858 859 860 861 862
	registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter.set(handle, new TypeDefinitionAdapter(this._documents, provider));
		this._proxy.$registerTypeDefinitionSupport(handle, selector);
		return this._createDisposable(handle);
	}

	$provideTypeDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
		return this._withAdapter(handle, TypeDefinitionAdapter, adapter => adapter.provideTypeDefinition(resource, position));
	}

J
Johannes Rieken 已提交
863 864
	// --- extra info

865
	registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
J
Johannes Rieken 已提交
866
		const handle = this._nextHandle();
867
		this._adapter.set(handle, new HoverAdapter(this._documents, provider, once((name: string, data: any) => {
868 869 870
			data['extension'] = extensionId;
			this._telemetry.$publicLog(name, data);
		})));
A
Alex Dima 已提交
871
		this._proxy.$registerHoverProvider(handle, selector);
J
Johannes Rieken 已提交
872 873 874
		return this._createDisposable(handle);
	}

875
	$provideHover(handle: number, resource: URI, position: IPosition): TPromise<modes.Hover> {
876
		return this._withAdapter(handle, HoverAdapter, adpater => adpater.provideHover(resource, position));
J
Johannes Rieken 已提交
877
	}
878

J
Johannes Rieken 已提交
879
	// --- occurrences
880 881 882

	registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
883
		this._adapter.set(handle, new DocumentHighlightAdapter(this._documents, provider));
884
		this._proxy.$registerDocumentHighlightProvider(handle, selector);
885 886 887
		return this._createDisposable(handle);
	}

888 889
	$provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]> {
		return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(resource, position));
890
	}
J
Johannes Rieken 已提交
891 892 893 894 895

	// --- references

	registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
896
		this._adapter.set(handle, new ReferenceAdapter(this._documents, provider));
J
Johannes Rieken 已提交
897 898 899 900
		this._proxy.$registerReferenceSupport(handle, selector);
		return this._createDisposable(handle);
	}

901 902
	$provideReferences(handle: number, resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]> {
		return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.provideReferences(resource, position, context));
J
Johannes Rieken 已提交
903 904
	}

J
Johannes Rieken 已提交
905 906 907 908
	// --- quick fix

	registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
909
		this._adapter.set(handle, new QuickFixAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
J
Johannes Rieken 已提交
910 911 912 913
		this._proxy.$registerQuickFixSupport(handle, selector);
		return this._createDisposable(handle);
	}

J
Johannes Rieken 已提交
914
	$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]> {
915
		return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.provideCodeActions(resource, range));
J
Johannes Rieken 已提交
916
	}
917 918 919 920 921

	// --- formatting

	registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
922
		this._adapter.set(handle, new DocumentFormattingAdapter(this._documents, provider));
923 924 925 926
		this._proxy.$registerDocumentFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

A
Alex Dima 已提交
927
	$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
928
		return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(resource, options));
929 930 931 932
	}

	registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
933
		this._adapter.set(handle, new RangeFormattingAdapter(this._documents, provider));
934 935 936 937
		this._proxy.$registerRangeFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

A
Alex Dima 已提交
938
	$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
939
		return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(resource, range, options));
940 941 942 943
	}

	registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
944
		this._adapter.set(handle, new OnTypeFormattingAdapter(this._documents, provider));
945 946 947 948
		this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters);
		return this._createDisposable(handle);
	}

A
Alex Dima 已提交
949
	$provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
950
		return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.provideOnTypeFormattingEdits(resource, position, ch, options));
951 952
	}

953 954 955 956
	// --- navigate types

	registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
957
		this._adapter.set(handle, new NavigateTypeAdapter(provider, this._heapService));
958 959 960 961
		this._proxy.$registerNavigateTypeSupport(handle);
		return this._createDisposable(handle);
	}

962
	$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]> {
963 964 965
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
	}

966
	$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation> {
967
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol));
968
	}
J
Johannes Rieken 已提交
969 970 971 972 973

	// --- rename

	registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
974
		this._adapter.set(handle, new RenameAdapter(this._documents, provider));
J
Johannes Rieken 已提交
975 976 977 978
		this._proxy.$registerRenameSupport(handle, selector);
		return this._createDisposable(handle);
	}

979 980
	$provideRenameEdits(handle: number, resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit> {
		return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(resource, position, newName));
J
Johannes Rieken 已提交
981
	}
982 983 984

	// --- suggestion

985
	registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
986
		const handle = this._nextHandle();
987
		this._adapter.set(handle, new SuggestAdapter(this._documents, this._commands.converter, provider));
988
		this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters, SuggestAdapter.supportsResolving(provider));
989 990 991
		return this._createDisposable(handle);
	}

992
	$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<IExtHostSuggestResult> {
993
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(resource, position));
994 995
	}

996 997
	$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(resource, position, suggestion));
998
	}
999

1000 1001 1002 1003
	$releaseCompletionItems(handle: number, id: number): void {
		this._withAdapter(handle, SuggestAdapter, adapter => adapter.releaseCompletionItems(id));
	}

1004 1005 1006 1007
	// --- parameter hints

	registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
1008
		this._adapter.set(handle, new SignatureHelpAdapter(this._documents, provider));
A
Alex Dima 已提交
1009
		this._proxy.$registerSignatureHelpProvider(handle, selector, triggerCharacters);
1010 1011 1012
		return this._createDisposable(handle);
	}

1013
	$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp> {
A
Alex Dima 已提交
1014
		return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(resource, position));
1015
	}
J
Johannes Rieken 已提交
1016

J
Johannes Rieken 已提交
1017 1018 1019 1020
	// --- links

	registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
1021
		this._adapter.set(handle, new LinkProviderAdapter(this._documents, this._heapService, provider));
J
Johannes Rieken 已提交
1022 1023 1024 1025
		this._proxy.$registerDocumentLinkProvider(handle, selector);
		return this._createDisposable(handle);
	}

1026
	$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]> {
J
Johannes Rieken 已提交
1027 1028 1029
		return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(resource));
	}

1030 1031 1032 1033
	$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink> {
		return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link));
	}

1034 1035
	registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Joao Moreno 已提交
1036
		this._adapter.set(handle, new ColorProviderAdapter(this._proxy, this._documents, this._colorFormatCache, provider));
1037 1038
		this._proxy.$registerDocumentColorProvider(handle, selector);
		return this._createDisposable(handle);
1039 1040
	}

1041
	$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]> {
1042 1043 1044
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(resource));
	}

1045
	$resolveDocumentColor(handle: number, color: modes.IColor, colorFormat: modes.ColorFormat): TPromise<string> {
1046 1047 1048
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.resolveColor(color, colorFormat));
	}

1049
	// --- configuration
J
Johannes Rieken 已提交
1050

J
Johannes Rieken 已提交
1051
	setLanguageConfiguration(languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
1052
		let { wordPattern } = configuration;
J
Johannes Rieken 已提交
1053

1054 1055 1056
		// check for a valid word pattern
		if (wordPattern && regExpLeadsToEndlessLoop(wordPattern)) {
			throw new Error(`Invalid language configuration: wordPattern '${wordPattern}' is not allowed to match the empty string.`);
J
Johannes Rieken 已提交
1057
		}
J
Johannes Rieken 已提交
1058

1059 1060 1061 1062 1063 1064
		// word definition
		if (wordPattern) {
			this._documents.setWordDefinitionFor(languageId, wordPattern);
		} else {
			this._documents.setWordDefinitionFor(languageId, null);
		}
1065

1066 1067 1068
		const handle = this._nextHandle();
		this._proxy.$setLanguageConfiguration(handle, languageId, configuration);
		return this._createDisposable(handle);
1069
	}
1070
}