extHostLanguageFeatures.ts 38.2 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, IRawColorFormatMap, 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
	private _documents: ExtHostDocuments;
473
	private _commands: CommandsConverter;
474 475
	private _provider: vscode.CompletionItemProvider;

476 477 478 479
	private _cache = new Map<number, vscode.CompletionItem[]>();
	private _idPool = 0;

	constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) {
480
		this._documents = documents;
481
		this._commands = commands;
482 483 484
		this._provider = provider;
	}

485
	provideCompletionItems(resource: URI, position: IPosition): TPromise<IExtHostSuggestResult> {
486

487
		const doc = this._documents.getDocumentData(resource).document;
488 489
		const pos = TypeConverters.toPosition(position);

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

492 493 494 495
			const _id = this._idPool++;

			const result: IExtHostSuggestResult = {
				_id,
496 497
				suggestions: [],
			};
498

499
			let list: CompletionList;
500
			if (!value) {
501
				// undefined and null are valid results
M
Matt Bierner 已提交
502
				return undefined;
503 504 505 506

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

507
			} else {
508 509
				list = value;
				result.incomplete = list.isIncomplete;
510
			}
511

512 513 514
			// the default text edit range
			const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos))
				.with({ end: pos });
515

516 517 518 519 520 521
			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);
522 523
				}
			}
524
			this._cache.set(_id, list.items);
525

526
			return result;
527 528 529
		});
	}

530
	resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
531 532

		if (typeof this._provider.resolveCompletionItem !== 'function') {
533 534
			return TPromise.as(suggestion);
		}
535

536 537
		const { _parentId, _id } = (<IExtHostSuggestion>suggestion);
		const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id];
538 539 540
		if (!item) {
			return TPromise.as(suggestion);
		}
541

542
		return asWinJsPromise(token => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
543 544 545 546 547 548 549 550

			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 });
551
			const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
552 553 554 555
			if (newSuggestion) {
				mixin(suggestion, newSuggestion, true);
			}

556
			return suggestion;
557 558
		});
	}
559

560 561 562 563 564
	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 已提交
565
		if (typeof item.label !== 'string' || item.label.length === 0) {
566
			console.warn('INVALID text edit -> must have at least a label');
M
Matt Bierner 已提交
567
			return undefined;
568 569
		}

570 571 572 573
		const result: IExtHostSuggestion = {
			//
			_id,
			_parentId,
574 575 576 577 578 579 580 581 582 583
			//
			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),
584 585
			command: this._commands.toInternal(item.command),
			commitCharacters: item.commitCharacters
586 587 588 589 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
		};

		// '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 已提交
620
			return undefined;
621 622 623 624
		}

		return result;
	}
625 626
}

A
Alex Dima 已提交
627
class SignatureHelpAdapter {
628

629
	private _documents: ExtHostDocuments;
630 631
	private _provider: vscode.SignatureHelpProvider;

632
	constructor(documents: ExtHostDocuments, provider: vscode.SignatureHelpProvider) {
633 634 635 636
		this._documents = documents;
		this._provider = provider;
	}

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

639
		const doc = this._documents.getDocumentData(resource).document;
640 641 642
		const pos = TypeConverters.toPosition(position);

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

J
Johannes Rieken 已提交
651 652 653
class LinkProviderAdapter {

	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
654
	private _heapService: ExtHostHeapService;
J
Johannes Rieken 已提交
655 656
	private _provider: vscode.DocumentLinkProvider;

J
Johannes Rieken 已提交
657
	constructor(documents: ExtHostDocuments, heapService: ExtHostHeapService, provider: vscode.DocumentLinkProvider) {
J
Johannes Rieken 已提交
658
		this._documents = documents;
J
Johannes Rieken 已提交
659
		this._heapService = heapService;
J
Johannes Rieken 已提交
660 661 662 663 664 665 666
		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 已提交
667 668
			if (!Array.isArray(links)) {
				return undefined;
J
Johannes Rieken 已提交
669
			}
J
Johannes Rieken 已提交
670 671 672 673 674 675 676 677
			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 已提交
678 679
		});
	}
680 681

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

		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;
		});
698
	}
J
Johannes Rieken 已提交
699 700
}

701 702
class ColorProviderAdapter {

J
Joao Moreno 已提交
703
	private static _colorFormatHandlePool: number = 0;
704

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

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

J
Joao Moreno 已提交
719 720 721
			const newRawColorFormats: IRawColorFormatMap = [];
			const getFormatId = (format: string) => {
				let id = this._colorFormatCache.get(format);
722

J
Joao Moreno 已提交
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
				if (typeof id !== 'number') {
					id = ColorProviderAdapter._colorFormatHandlePool++;
					this._colorFormatCache.set(format, id);
					newRawColorFormats.push([id, format]);
				}

				return id;
			};

			const colorInfos: IRawColorInfo[] = colors.map(ci => {
				const availableFormats = ci.availableFormats.map(format => {
					if (typeof format === 'string') {
						return getFormatId(format);
					} else {
						return [getFormatId(format.opaque), getFormatId(format.transparent)] as [number, number];
					}
739 740
				});

J
Joao Moreno 已提交
741 742 743
				return {
					color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] as [number, number, number, number],
					availableFormats: availableFormats,
744
					range: TypeConverters.fromRange(ci.range)
J
Joao Moreno 已提交
745 746 747 748 749
				};
			});

			this._proxy.$registerColorFormats(newRawColorFormats);
			return colorInfos;
750 751 752 753
		});
	}
}

754
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
755
	| DocumentHighlightAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
756
	| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
757
	| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
J
Johannes Rieken 已提交
758

759
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
J
Johannes Rieken 已提交
760

761
	private static _handlePool: number = 0;
J
Johannes Rieken 已提交
762

763
	private _proxy: MainThreadLanguageFeaturesShape;
764
	private _telemetry: MainThreadTelemetryShape;
765
	private _documents: ExtHostDocuments;
766
	private _commands: ExtHostCommands;
767
	private _heapService: ExtHostHeapService;
768
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
769
	private _adapter = new Map<number, Adapter>();
J
Joao Moreno 已提交
770
	private _colorFormatCache = new Map<string, number>();
J
Johannes Rieken 已提交
771

772
	constructor(
773
		mainContext: IMainContext,
774
		documents: ExtHostDocuments,
775
		commands: ExtHostCommands,
J
Johannes Rieken 已提交
776
		heapMonitor: ExtHostHeapService,
777 778
		diagnostics: ExtHostDiagnostics
	) {
779
		this._proxy = mainContext.get(MainContext.MainThreadLanguageFeatures);
780
		this._telemetry = mainContext.get(MainContext.MainThreadTelemetry);
781 782
		this._documents = documents;
		this._commands = commands;
783
		this._heapService = heapMonitor;
784
		this._diagnostics = diagnostics;
J
Johannes Rieken 已提交
785 786 787 788
	}

	private _createDisposable(handle: number): Disposable {
		return new Disposable(() => {
J
Johannes Rieken 已提交
789
			this._adapter.delete(handle);
J
Johannes Rieken 已提交
790 791 792 793
			this._proxy.$unregister(handle);
		});
	}

794 795 796 797
	private _nextHandle(): number {
		return ExtHostLanguageFeatures._handlePool++;
	}

798
	private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => TPromise<R>): TPromise<R> {
J
Johannes Rieken 已提交
799
		let adapter = this._adapter.get(handle);
J
Johannes Rieken 已提交
800
		if (!(adapter instanceof ctor)) {
801
			return TPromise.wrapError<R>(new Error('no adapter found'));
J
Johannes Rieken 已提交
802
		}
J
Johannes Rieken 已提交
803
		return callback(<any>adapter);
804 805
	}

J
Johannes Rieken 已提交
806 807 808
	// --- outline

	registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
809
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
810
		this._adapter.set(handle, new OutlineAdapter(this._documents, provider));
811
		this._proxy.$registerOutlineSupport(handle, selector);
J
Johannes Rieken 已提交
812 813 814
		return this._createDisposable(handle);
	}

815 816
	$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]> {
		return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(resource));
J
Johannes Rieken 已提交
817
	}
818 819 820 821 822

	// --- code lens

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

J
Johannes Rieken 已提交
825
		this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider));
826 827 828 829 830 831 832 833 834
		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;
835 836
	}

837 838
	$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(resource));
839 840
	}

841 842
	$resolveCodeLens(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(resource, symbol));
J
Johannes Rieken 已提交
843 844 845 846 847 848
	}

	// --- declaration

	registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
849
		this._adapter.set(handle, new DefinitionAdapter(this._documents, provider));
J
Johannes Rieken 已提交
850 851
		this._proxy.$registerDeclaractionSupport(handle, selector);
		return this._createDisposable(handle);
852 853
	}

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

M
Matt Bierner 已提交
858
	registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
859 860 861 862 863 864
		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 已提交
865 866
	$provideImplementation(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
		return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(resource, position));
867 868
	}

869 870 871 872 873 874 875 876 877 878 879
	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 已提交
880 881
	// --- extra info

882
	registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
J
Johannes Rieken 已提交
883
		const handle = this._nextHandle();
884
		this._adapter.set(handle, new HoverAdapter(this._documents, provider, once((name: string, data: any) => {
885 886 887
			data['extension'] = extensionId;
			this._telemetry.$publicLog(name, data);
		})));
A
Alex Dima 已提交
888
		this._proxy.$registerHoverProvider(handle, selector);
J
Johannes Rieken 已提交
889 890 891
		return this._createDisposable(handle);
	}

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

J
Johannes Rieken 已提交
896
	// --- occurrences
897 898 899

	registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
900
		this._adapter.set(handle, new DocumentHighlightAdapter(this._documents, provider));
901
		this._proxy.$registerDocumentHighlightProvider(handle, selector);
902 903 904
		return this._createDisposable(handle);
	}

905 906
	$provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]> {
		return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(resource, position));
907
	}
J
Johannes Rieken 已提交
908 909 910 911 912

	// --- references

	registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
913
		this._adapter.set(handle, new ReferenceAdapter(this._documents, provider));
J
Johannes Rieken 已提交
914 915 916 917
		this._proxy.$registerReferenceSupport(handle, selector);
		return this._createDisposable(handle);
	}

918 919
	$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 已提交
920 921
	}

J
Johannes Rieken 已提交
922 923 924 925
	// --- quick fix

	registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
926
		this._adapter.set(handle, new QuickFixAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
J
Johannes Rieken 已提交
927 928 929 930
		this._proxy.$registerQuickFixSupport(handle, selector);
		return this._createDisposable(handle);
	}

J
Johannes Rieken 已提交
931
	$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]> {
932
		return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.provideCodeActions(resource, range));
J
Johannes Rieken 已提交
933
	}
934 935 936 937 938

	// --- formatting

	registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
939
		this._adapter.set(handle, new DocumentFormattingAdapter(this._documents, provider));
940 941 942 943
		this._proxy.$registerDocumentFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

A
Alex Dima 已提交
944
	$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
945
		return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(resource, options));
946 947 948 949
	}

	registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
950
		this._adapter.set(handle, new RangeFormattingAdapter(this._documents, provider));
951 952 953 954
		this._proxy.$registerRangeFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

A
Alex Dima 已提交
955
	$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
956
		return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(resource, range, options));
957 958 959 960
	}

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

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

970 971 972 973
	// --- navigate types

	registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
974
		this._adapter.set(handle, new NavigateTypeAdapter(provider, this._heapService));
975 976 977 978
		this._proxy.$registerNavigateTypeSupport(handle);
		return this._createDisposable(handle);
	}

979
	$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]> {
980 981 982
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
	}

983
	$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation> {
984
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol));
985
	}
J
Johannes Rieken 已提交
986 987 988 989 990

	// --- rename

	registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
991
		this._adapter.set(handle, new RenameAdapter(this._documents, provider));
J
Johannes Rieken 已提交
992 993 994 995
		this._proxy.$registerRenameSupport(handle, selector);
		return this._createDisposable(handle);
	}

996 997
	$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 已提交
998
	}
999 1000 1001

	// --- suggestion

1002
	registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
1003
		const handle = this._nextHandle();
1004
		this._adapter.set(handle, new SuggestAdapter(this._documents, this._commands.converter, provider));
1005 1006 1007 1008
		this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters);
		return this._createDisposable(handle);
	}

1009
	$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<IExtHostSuggestResult> {
1010
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(resource, position));
1011 1012
	}

1013 1014
	$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(resource, position, suggestion));
1015
	}
1016

1017 1018 1019 1020
	$releaseCompletionItems(handle: number, id: number): void {
		this._withAdapter(handle, SuggestAdapter, adapter => adapter.releaseCompletionItems(id));
	}

1021 1022 1023 1024
	// --- parameter hints

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

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

J
Johannes Rieken 已提交
1034 1035 1036 1037
	// --- links

	registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
1038
		this._adapter.set(handle, new LinkProviderAdapter(this._documents, this._heapService, provider));
J
Johannes Rieken 已提交
1039 1040 1041 1042
		this._proxy.$registerDocumentLinkProvider(handle, selector);
		return this._createDisposable(handle);
	}

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

1047 1048 1049 1050
	$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink> {
		return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link));
	}

1051 1052
	registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Joao Moreno 已提交
1053
		this._adapter.set(handle, new ColorProviderAdapter(this._proxy, this._documents, this._colorFormatCache, provider));
1054 1055
		this._proxy.$registerDocumentColorProvider(handle, selector);
		return this._createDisposable(handle);
1056 1057
	}

1058
	$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]> {
1059 1060 1061
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(resource));
	}

1062
	// --- configuration
J
Johannes Rieken 已提交
1063

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

1067 1068 1069
		// 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 已提交
1070
		}
J
Johannes Rieken 已提交
1071

1072 1073 1074 1075 1076 1077
		// word definition
		if (wordPattern) {
			this._documents.setWordDefinitionFor(languageId, wordPattern);
		} else {
			this._documents.setWordDefinitionFor(languageId, null);
		}
1078

1079 1080 1081
		const handle = this._nextHandle();
		this._proxy.$setLanguageConfiguration(handle, languageId, configuration);
		return this._createDisposable(handle);
1082
	}
1083
}