extHostLanguageFeatures.ts 38.9 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, Color } 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';
18
import { ExtHostDiagnostics, DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics';
19
import { asWinJsPromise } from 'vs/base/common/async';
20
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion, IWorkspaceSymbols, IWorkspaceSymbol, IdObject } from './extHost.protocol';
J
Johannes Rieken 已提交
21
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
22 23
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
24
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
J
Johannes Rieken 已提交
25 26 27

// --- adapter

28
class OutlineAdapter {
J
Johannes Rieken 已提交
29

30
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
31 32
	private _provider: vscode.DocumentSymbolProvider;

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

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

49
class CodeLensAdapter {
50

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

53
	private _documents: ExtHostDocuments;
54 55
	private _commands: CommandsConverter;
	private _heapService: ExtHostHeapService;
56 57
	private _provider: vscode.CodeLensProvider;

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

65
	provideCodeLenses(resource: URI): TPromise<modes.ICodeLensSymbol[]> {
66
		const doc = this._documents.getDocumentData(resource).document;
67

68 69 70 71 72 73 74 75
		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);
76 77
				});
			}
M
Matt Bierner 已提交
78
			return undefined;
79
		});
80 81
	}

82
	resolveCodeLens(resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
83

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

89 90 91 92 93 94
		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));
		}
95

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

104
class DefinitionAdapter {
105
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
106 107
	private _provider: vscode.DefinitionProvider;

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

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

127 128
class ImplementationAdapter {
	private _documents: ExtHostDocuments;
M
Matt Bierner 已提交
129
	private _provider: vscode.ImplementationProvider;
130

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

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


174
class HoverAdapter {
J
Johannes Rieken 已提交
175

176 177 178 179 180
	constructor(
		private readonly _documents: ExtHostDocuments,
		private readonly _provider: vscode.HoverProvider,
	) {
		//
J
Johannes Rieken 已提交
181 182
	}

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

185
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
186 187 188
		let pos = TypeConverters.toPosition(position);

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

199
			return TypeConverters.fromHover(value);
J
Johannes Rieken 已提交
200 201 202 203
		});
	}
}

204
class DocumentHighlightAdapter {
205

206
	private _documents: ExtHostDocuments;
207 208
	private _provider: vscode.DocumentHighlightProvider;

209
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentHighlightProvider) {
210 211 212 213
		this._documents = documents;
		this._provider = provider;
	}

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

216
		let doc = this._documents.getDocumentData(resource).document;
217 218 219 220
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => {
			if (Array.isArray(value)) {
221
				return value.map(DocumentHighlightAdapter._convertDocumentHighlight);
222
			}
M
Matt Bierner 已提交
223
			return undefined;
224 225 226
		});
	}

227
	private static _convertDocumentHighlight(documentHighlight: vscode.DocumentHighlight): modes.DocumentHighlight {
228 229
		return {
			range: TypeConverters.fromRange(documentHighlight.range),
230
			kind: documentHighlight.kind
B
Benjamin Pasero 已提交
231
		};
232 233 234
	}
}

235
class ReferenceAdapter {
J
Johannes Rieken 已提交
236

237
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
238 239
	private _provider: vscode.ReferenceProvider;

240
	constructor(documents: ExtHostDocuments, provider: vscode.ReferenceProvider) {
J
Johannes Rieken 已提交
241 242 243 244
		this._documents = documents;
		this._provider = provider;
	}

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

249
		return asWinJsPromise(token => this._provider.provideReferences(doc, pos, context, token)).then(value => {
J
Johannes Rieken 已提交
250
			if (Array.isArray(value)) {
J
Johannes Rieken 已提交
251
				return value.map(TypeConverters.location.from);
J
Johannes Rieken 已提交
252
			}
M
Matt Bierner 已提交
253
			return undefined;
J
Johannes Rieken 已提交
254 255 256 257
		});
	}
}

258
class QuickFixAdapter {
J
Johannes Rieken 已提交
259

260
	private _documents: ExtHostDocuments;
261
	private _commands: CommandsConverter;
262
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
263 264
	private _provider: vscode.CodeActionProvider;

J
Johannes Rieken 已提交
265
	constructor(documents: ExtHostDocuments, commands: CommandsConverter, diagnostics: ExtHostDiagnostics, provider: vscode.CodeActionProvider) {
J
Johannes Rieken 已提交
266 267
		this._documents = documents;
		this._commands = commands;
268
		this._diagnostics = diagnostics;
J
Johannes Rieken 已提交
269 270 271
		this._provider = provider;
	}

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

274
		const doc = this._documents.getDocumentData(resource).document;
275
		const ran = <vscode.Range>TypeConverters.toRange(range);
276 277 278 279 280
		const allDiagnostics: vscode.Diagnostic[] = [];

		this._diagnostics.forEach(collection => {
			if (collection.has(resource)) {
				for (let diagnostic of collection.get(resource)) {
281
					if (ran.contains(diagnostic.range)) {
282 283 284 285
						allDiagnostics.push(diagnostic);
					}
				}
			}
J
Johannes Rieken 已提交
286 287
		});

288 289 290 291 292
		return asWinJsPromise(token =>
			this._provider.provideCodeActions2
				? this._provider.provideCodeActions2(doc, ran, { diagnostics: allDiagnostics }, token)
				: this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)
		).then(commands => {
J
Johannes Rieken 已提交
293
			if (!Array.isArray(commands)) {
M
Matt Bierner 已提交
294
				return undefined;
J
Johannes Rieken 已提交
295
			}
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
			return commands.map((action): modes.CodeAction => {
				if (!action) {
					return undefined;
				}

				if (typeof action.command === 'string') {
					return this._commands.toInternal(action as vscode.Command);
				}

				const codeAction = action as vscode.CodeAction;
				return {
					title: codeAction.title,
					command: codeAction.command ? this._commands.toInternal(codeAction.command) : undefined,
					edits: codeAction.edits
						? Array.isArray(codeAction.edits)
							? TypeConverters.WorkspaceEdit.fromTextEdits(resource, codeAction.edits)
							: TypeConverters.WorkspaceEdit.from(codeAction.edits)
						: undefined,
					diagnostics: codeAction.diagnostics
						? codeAction.diagnostics.map(DiagnosticCollection.toMarkerData)
						: undefined
				} as modes.CodeAction;
			});
J
Johannes Rieken 已提交
319 320 321 322
		});
	}
}

323
class DocumentFormattingAdapter {
324

325
	private _documents: ExtHostDocuments;
326 327
	private _provider: vscode.DocumentFormattingEditProvider;

328
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentFormattingEditProvider) {
329 330 331 332
		this._documents = documents;
		this._provider = provider;
	}

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

335
		const { document } = this._documents.getDocumentData(resource);
336 337

		return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(document, <any>options, token)).then(value => {
338
			if (Array.isArray(value)) {
339
				return value.map(TypeConverters.TextEdit.from);
340
			}
M
Matt Bierner 已提交
341
			return undefined;
342 343 344 345
		});
	}
}

346
class RangeFormattingAdapter {
347

348
	private _documents: ExtHostDocuments;
349 350
	private _provider: vscode.DocumentRangeFormattingEditProvider;

351
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentRangeFormattingEditProvider) {
352 353 354 355
		this._documents = documents;
		this._provider = provider;
	}

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

358
		const { document } = this._documents.getDocumentData(resource);
359
		const ran = TypeConverters.toRange(range);
360

361
		return asWinJsPromise(token => this._provider.provideDocumentRangeFormattingEdits(document, ran, <any>options, token)).then(value => {
362
			if (Array.isArray(value)) {
363
				return value.map(TypeConverters.TextEdit.from);
364
			}
M
Matt Bierner 已提交
365
			return undefined;
366 367 368 369
		});
	}
}

370
class OnTypeFormattingAdapter {
371

372
	private _documents: ExtHostDocuments;
373 374
	private _provider: vscode.OnTypeFormattingEditProvider;

375
	constructor(documents: ExtHostDocuments, provider: vscode.OnTypeFormattingEditProvider) {
376 377 378 379
		this._documents = documents;
		this._provider = provider;
	}

380
	autoFormatTriggerCharacters: string[] = []; // not here
381

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

384
		const { document } = this._documents.getDocumentData(resource);
385
		const pos = TypeConverters.toPosition(position);
386

J
Johannes Rieken 已提交
387
		return asWinJsPromise(token => this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token)).then(value => {
388
			if (Array.isArray(value)) {
389
				return value.map(TypeConverters.TextEdit.from);
390
			}
M
Matt Bierner 已提交
391
			return undefined;
392 393 394 395
		});
	}
}

396
class NavigateTypeAdapter {
397

398 399 400
	private readonly _symbolCache: { [id: number]: vscode.SymbolInformation } = Object.create(null);
	private readonly _resultCache: { [id: number]: [number, number] } = Object.create(null);
	private readonly _provider: vscode.WorkspaceSymbolProvider;
401

402
	constructor(provider: vscode.WorkspaceSymbolProvider) {
403 404 405
		this._provider = provider;
	}

406 407
	provideWorkspaceSymbols(search: string): TPromise<IWorkspaceSymbols> {
		const result: IWorkspaceSymbols = IdObject.mixin({ symbols: [] });
408
		return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
409 410
			if (!isFalsyOrEmpty(value)) {
				for (const item of value) {
M
Matt Bierner 已提交
411 412 413 414 415
					if (item) {
						const symbol = IdObject.mixin(TypeConverters.fromSymbolInformation(item));
						this._symbolCache[symbol._id] = item;
						result.symbols.push(symbol);
					}
416
				}
417
			}
418 419 420
		}).then(() => {
			this._resultCache[result._id] = [result.symbols[0]._id, result.symbols[result.symbols.length - 1]._id];
			return result;
421 422
		});
	}
423

424
	resolveWorkspaceSymbol(symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
425 426

		if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
427
			return TPromise.as(symbol);
428 429
		}

430 431 432 433
		const item = this._symbolCache[symbol._id];
		if (item) {
			return asWinJsPromise(token => this._provider.resolveWorkspaceSymbol(item, token)).then(value => {
				return value && mixin(symbol, TypeConverters.fromSymbolInformation(value), true);
434
			});
435
		}
M
Matt Bierner 已提交
436
		return undefined;
437
	}
438 439 440 441 442 443 444 445 446 447

	releaseWorkspaceSymbols(id: number): any {
		const range = this._resultCache[id];
		if (range) {
			for (let [from, to] = range; from <= to; from++) {
				delete this._symbolCache[from];
			}
			delete this._resultCache[id];
		}
	}
448 449
}

450
class RenameAdapter {
J
Johannes Rieken 已提交
451

452
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
453 454
	private _provider: vscode.RenameProvider;

455
	constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) {
J
Johannes Rieken 已提交
456 457 458 459
		this._documents = documents;
		this._provider = provider;
	}

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

462
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
463 464 465 466
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {
			if (!value) {
M
Matt Bierner 已提交
467
				return undefined;
J
Johannes Rieken 已提交
468
			}
469
			return TypeConverters.WorkspaceEdit.from(value);
J
Johannes Rieken 已提交
470 471
		}, err => {
			if (typeof err === 'string') {
472
				return <modes.WorkspaceEdit>{
J
Johannes Rieken 已提交
473 474 475
					edits: undefined,
					rejectReason: err
				};
J
Johannes Rieken 已提交
476 477 478 479 480 481 482 483
			} else if (err instanceof Error && typeof err.message === 'string') {
				return <modes.WorkspaceEdit>{
					edits: undefined,
					rejectReason: err.message
				};
			} else {
				// generic error
				return TPromise.wrapError<modes.WorkspaceEdit>(err);
J
Johannes Rieken 已提交
484 485 486 487 488
			}
		});
	}
}

489

490
class SuggestAdapter {
491

492 493 494 495
	static supportsResolving(provider: vscode.CompletionItemProvider): boolean {
		return typeof provider.resolveCompletionItem === 'function';
	}

496
	private _documents: ExtHostDocuments;
497
	private _commands: CommandsConverter;
498 499
	private _provider: vscode.CompletionItemProvider;

500 501 502 503
	private _cache = new Map<number, vscode.CompletionItem[]>();
	private _idPool = 0;

	constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) {
504
		this._documents = documents;
505
		this._commands = commands;
506 507 508
		this._provider = provider;
	}

509
	provideCompletionItems(resource: URI, position: IPosition, context: modes.SuggestContext): TPromise<IExtHostSuggestResult> {
510

511
		const doc = this._documents.getDocumentData(resource).document;
512 513
		const pos = TypeConverters.toPosition(position);

514
		return asWinJsPromise<vscode.CompletionItem[] | vscode.CompletionList>(token => {
M
Matt Bierner 已提交
515
			return this._provider.provideCompletionItems(doc, pos, token, TypeConverters.CompletionContext.from(context));
516
		}).then(value => {
517

518 519 520 521
			const _id = this._idPool++;

			const result: IExtHostSuggestResult = {
				_id,
522 523
				suggestions: [],
			};
524

525
			let list: CompletionList;
526
			if (!value) {
527
				// undefined and null are valid results
M
Matt Bierner 已提交
528
				return undefined;
529 530 531 532

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

533
			} else {
534 535
				list = value;
				result.incomplete = list.isIncomplete;
536
			}
537

538 539 540
			// the default text edit range
			const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos))
				.with({ end: pos });
541

542 543 544 545 546 547
			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);
548 549
				}
			}
550
			this._cache.set(_id, list.items);
551

552
			return result;
553 554 555
		});
	}

556
	resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
557 558

		if (typeof this._provider.resolveCompletionItem !== 'function') {
559 560
			return TPromise.as(suggestion);
		}
561

562 563
		const { _parentId, _id } = (<IExtHostSuggestion>suggestion);
		const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id];
564 565 566
		if (!item) {
			return TPromise.as(suggestion);
		}
567

568
		return asWinJsPromise(token => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
569 570 571 572 573 574 575 576

			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 });
577
			const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
578 579 580 581
			if (newSuggestion) {
				mixin(suggestion, newSuggestion, true);
			}

582
			return suggestion;
583 584
		});
	}
585

586 587 588 589 590
	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 已提交
591
		if (typeof item.label !== 'string' || item.label.length === 0) {
592
			console.warn('INVALID text edit -> must have at least a label');
M
Matt Bierner 已提交
593
			return undefined;
594 595
		}

596 597 598 599
		const result: IExtHostSuggestion = {
			//
			_id,
			_parentId,
600 601 602 603 604 605 606 607 608 609
			//
			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),
610 611
			command: this._commands.toInternal(item.command),
			commitCharacters: item.commitCharacters
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
		};

		// '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 已提交
646
			return undefined;
647 648 649 650
		}

		return result;
	}
651 652
}

A
Alex Dima 已提交
653
class SignatureHelpAdapter {
654

655
	private _documents: ExtHostDocuments;
656 657
	private _provider: vscode.SignatureHelpProvider;

658
	constructor(documents: ExtHostDocuments, provider: vscode.SignatureHelpProvider) {
659 660 661 662
		this._documents = documents;
		this._provider = provider;
	}

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

665
		const doc = this._documents.getDocumentData(resource).document;
666 667 668
		const pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideSignatureHelp(doc, pos, token)).then(value => {
669
			if (value) {
670
				return TypeConverters.SignatureHelp.from(value);
671
			}
M
Matt Bierner 已提交
672
			return undefined;
673 674 675 676
		});
	}
}

J
Johannes Rieken 已提交
677 678 679
class LinkProviderAdapter {

	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
680
	private _heapService: ExtHostHeapService;
J
Johannes Rieken 已提交
681 682
	private _provider: vscode.DocumentLinkProvider;

J
Johannes Rieken 已提交
683
	constructor(documents: ExtHostDocuments, heapService: ExtHostHeapService, provider: vscode.DocumentLinkProvider) {
J
Johannes Rieken 已提交
684
		this._documents = documents;
J
Johannes Rieken 已提交
685
		this._heapService = heapService;
J
Johannes Rieken 已提交
686 687 688 689 690 691 692
		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 已提交
693 694
			if (!Array.isArray(links)) {
				return undefined;
J
Johannes Rieken 已提交
695
			}
J
Johannes Rieken 已提交
696 697 698 699 700 701 702 703
			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 已提交
704 705
		});
	}
706 707

	resolveLink(link: modes.ILink): TPromise<modes.ILink> {
J
Johannes Rieken 已提交
708 709
		if (typeof this._provider.resolveDocumentLink !== 'function') {
			return undefined;
710
		}
J
Johannes Rieken 已提交
711 712 713 714 715 716 717 718 719 720 721 722 723

		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;
		});
724
	}
J
Johannes Rieken 已提交
725 726
}

727 728
class ColorProviderAdapter {

J
Joao Moreno 已提交
729 730 731 732
	constructor(
		private _documents: ExtHostDocuments,
		private _provider: vscode.DocumentColorProvider
	) { }
733

734
	provideColors(resource: URI): TPromise<IRawColorInfo[]> {
735
		const doc = this._documents.getDocumentData(resource).document;
J
Joao Moreno 已提交
736 737 738
		return asWinJsPromise(token => this._provider.provideDocumentColors(doc, token)).then(colors => {
			if (!Array.isArray(colors)) {
				return [];
739 740
			}

J
Joao Moreno 已提交
741 742 743
			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],
744
					range: TypeConverters.fromRange(ci.range)
J
Joao Moreno 已提交
745 746 747 748
				};
			});

			return colorInfos;
749 750
		});
	}
751

752 753 754 755 756 757
	provideColorPresentations(resource: URI, raw: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
		const document = this._documents.getDocumentData(resource).document;
		const range = TypeConverters.toRange(raw.range);
		const color = new Color(raw.color[0], raw.color[1], raw.color[2], raw.color[3]);
		return asWinJsPromise(token => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => {
			return value.map(TypeConverters.ColorPresentation.from);
758
		});
759
	}
760 761
}

762
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
763
	| DocumentHighlightAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
764
	| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
765
	| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
J
Johannes Rieken 已提交
766

767
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
J
Johannes Rieken 已提交
768

769
	private static _handlePool: number = 0;
J
Johannes Rieken 已提交
770

771
	private _proxy: MainThreadLanguageFeaturesShape;
772
	private _documents: ExtHostDocuments;
773
	private _commands: ExtHostCommands;
774
	private _heapService: ExtHostHeapService;
775
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
776
	private _adapter = new Map<number, Adapter>();
J
Johannes Rieken 已提交
777

778
	constructor(
779
		mainContext: IMainContext,
780
		documents: ExtHostDocuments,
781
		commands: ExtHostCommands,
J
Johannes Rieken 已提交
782
		heapMonitor: ExtHostHeapService,
783 784
		diagnostics: ExtHostDiagnostics
	) {
785
		this._proxy = mainContext.get(MainContext.MainThreadLanguageFeatures);
786 787
		this._documents = documents;
		this._commands = commands;
788
		this._heapService = heapMonitor;
789
		this._diagnostics = diagnostics;
J
Johannes Rieken 已提交
790 791 792 793
	}

	private _createDisposable(handle: number): Disposable {
		return new Disposable(() => {
J
Johannes Rieken 已提交
794
			this._adapter.delete(handle);
J
Johannes Rieken 已提交
795 796 797 798
			this._proxy.$unregister(handle);
		});
	}

799 800 801 802
	private _nextHandle(): number {
		return ExtHostLanguageFeatures._handlePool++;
	}

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

J
Johannes Rieken 已提交
811 812 813
	// --- outline

	registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
814
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
815
		this._adapter.set(handle, new OutlineAdapter(this._documents, provider));
816
		this._proxy.$registerOutlineSupport(handle, selector);
J
Johannes Rieken 已提交
817 818 819
		return this._createDisposable(handle);
	}

820 821
	$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]> {
		return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(resource));
J
Johannes Rieken 已提交
822
	}
823 824 825 826 827

	// --- code lens

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

J
Johannes Rieken 已提交
830
		this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider));
831 832 833 834 835 836 837 838 839
		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;
840 841
	}

842 843
	$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(resource));
844 845
	}

846 847
	$resolveCodeLens(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(resource, symbol));
J
Johannes Rieken 已提交
848 849 850 851 852 853
	}

	// --- declaration

	registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
854
		this._adapter.set(handle, new DefinitionAdapter(this._documents, provider));
J
Johannes Rieken 已提交
855 856
		this._proxy.$registerDeclaractionSupport(handle, selector);
		return this._createDisposable(handle);
857 858
	}

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

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

874 875 876 877 878 879 880 881 882 883 884
	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 已提交
885 886
	// --- extra info

887
	registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
J
Johannes Rieken 已提交
888
		const handle = this._nextHandle();
889
		this._adapter.set(handle, new HoverAdapter(this._documents, provider));
A
Alex Dima 已提交
890
		this._proxy.$registerHoverProvider(handle, selector);
J
Johannes Rieken 已提交
891 892 893
		return this._createDisposable(handle);
	}

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

J
Johannes Rieken 已提交
898
	// --- occurrences
899 900 901

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

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

	// --- references

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

920 921
	$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 已提交
922 923
	}

J
Johannes Rieken 已提交
924 925 926 927
	// --- quick fix

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

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

	// --- formatting

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

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

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

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

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

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

972 973 974 975
	// --- navigate types

	registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
		const handle = this._nextHandle();
976
		this._adapter.set(handle, new NavigateTypeAdapter(provider));
977 978 979 980
		this._proxy.$registerNavigateTypeSupport(handle);
		return this._createDisposable(handle);
	}

981
	$provideWorkspaceSymbols(handle: number, search: string): TPromise<IWorkspaceSymbols> {
982 983 984
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
	}

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

989 990 991 992
	$releaseWorkspaceSymbols(handle: number, id: number) {
		this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.releaseWorkspaceSymbols(id));
	}

J
Johannes Rieken 已提交
993 994 995 996
	// --- rename

	registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
997
		this._adapter.set(handle, new RenameAdapter(this._documents, provider));
J
Johannes Rieken 已提交
998 999 1000 1001
		this._proxy.$registerRenameSupport(handle, selector);
		return this._createDisposable(handle);
	}

1002 1003
	$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 已提交
1004
	}
1005 1006 1007

	// --- suggestion

1008
	registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
1009
		const handle = this._nextHandle();
1010
		this._adapter.set(handle, new SuggestAdapter(this._documents, this._commands.converter, provider));
1011
		this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters, SuggestAdapter.supportsResolving(provider));
1012 1013 1014
		return this._createDisposable(handle);
	}

1015 1016
	$provideCompletionItems(handle: number, resource: URI, position: IPosition, context: modes.SuggestContext): TPromise<IExtHostSuggestResult> {
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(resource, position, context));
1017 1018
	}

1019 1020
	$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(resource, position, suggestion));
1021
	}
1022

1023 1024 1025 1026
	$releaseCompletionItems(handle: number, id: number): void {
		this._withAdapter(handle, SuggestAdapter, adapter => adapter.releaseCompletionItems(id));
	}

1027 1028 1029 1030
	// --- parameter hints

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

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

J
Johannes Rieken 已提交
1040 1041 1042 1043
	// --- links

	registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
1044
		this._adapter.set(handle, new LinkProviderAdapter(this._documents, this._heapService, provider));
J
Johannes Rieken 已提交
1045 1046 1047 1048
		this._proxy.$registerDocumentLinkProvider(handle, selector);
		return this._createDisposable(handle);
	}

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

1053 1054 1055 1056
	$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink> {
		return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link));
	}

1057 1058
	registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
		const handle = this._nextHandle();
1059
		this._adapter.set(handle, new ColorProviderAdapter(this._documents, provider));
1060 1061
		this._proxy.$registerDocumentColorProvider(handle, selector);
		return this._createDisposable(handle);
1062 1063
	}

1064
	$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]> {
1065 1066 1067
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(resource));
	}

1068 1069
	$provideColorPresentations(handle: number, resource: URI, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(resource, colorInfo));
1070 1071
	}

1072
	// --- configuration
J
Johannes Rieken 已提交
1073

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

1077 1078 1079
		// 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 已提交
1080
		}
J
Johannes Rieken 已提交
1081

1082 1083 1084 1085 1086 1087
		// word definition
		if (wordPattern) {
			this._documents.setWordDefinitionFor(languageId, wordPattern);
		} else {
			this._documents.setWordDefinitionFor(languageId, null);
		}
1088

1089 1090 1091
		const handle = this._nextHandle();
		this._proxy.$setLanguageConfiguration(handle, languageId, configuration);
		return this._createDisposable(handle);
1092
	}
1093
}