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

7
import URI, { UriComponents } 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, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration } 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 259 260 261 262
export interface CustomCodeAction extends modes.CodeAction {
	_isSynthetic?: boolean;
}

class CodeActionAdapter {
J
Johannes Rieken 已提交
263

264
	private _documents: ExtHostDocuments;
265
	private _commands: CommandsConverter;
266
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
267 268
	private _provider: vscode.CodeActionProvider;

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

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

278
		const doc = this._documents.getDocumentData(resource).document;
279
		const ran = <vscode.Range>TypeConverters.toRange(range);
280 281 282 283 284
		const allDiagnostics: vscode.Diagnostic[] = [];

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

292 293 294 295 296
		return asWinJsPromise(token => this._provider.provideCodeActions2
			? this._provider.provideCodeActions2(doc, ran, { diagnostics: allDiagnostics }, token)
			: this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)
		).then(commandsOrActions => {
			if (isFalsyOrEmpty(commandsOrActions)) {
M
Matt Bierner 已提交
297
				return undefined;
J
Johannes Rieken 已提交
298
			}
299 300 301 302
			const result: CustomCodeAction[] = [];
			for (const candidate of commandsOrActions) {
				if (!candidate) {
					continue;
303
				}
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
				if (CodeActionAdapter._isCommand(candidate)) {
					// old school: synthetic code action
					result.push({
						_isSynthetic: true,
						title: candidate.title,
						command: this._commands.toInternal(candidate),
					});
				} else {
					// new school: convert code action
					result.push({
						title: candidate.title,
						command: candidate.command && this._commands.toInternal(candidate.command),
						diagnostics: candidate.diagnostics && candidate.diagnostics.map(DiagnosticCollection.toMarkerData),
						edits: Array.isArray(candidate.edits)
							? TypeConverters.WorkspaceEdit.fromTextEdits(resource, candidate.edits)
							: candidate.edits && TypeConverters.WorkspaceEdit.from(candidate.edits),
					});
321
				}
322
			}
323

324
			return result;
J
Johannes Rieken 已提交
325 326
		});
	}
327 328 329 330

	private static _isCommand(thing: any): thing is vscode.Command {
		return typeof (<vscode.Command>thing).command === 'string' && typeof (<vscode.Command>thing).title === 'string';
	}
J
Johannes Rieken 已提交
331 332
}

333
class DocumentFormattingAdapter {
334

335
	private _documents: ExtHostDocuments;
336 337
	private _provider: vscode.DocumentFormattingEditProvider;

338
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentFormattingEditProvider) {
339 340 341 342
		this._documents = documents;
		this._provider = provider;
	}

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

345
		const { document } = this._documents.getDocumentData(resource);
346 347

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

356
class RangeFormattingAdapter {
357

358
	private _documents: ExtHostDocuments;
359 360
	private _provider: vscode.DocumentRangeFormattingEditProvider;

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

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

368
		const { document } = this._documents.getDocumentData(resource);
369
		const ran = TypeConverters.toRange(range);
370

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

380
class OnTypeFormattingAdapter {
381

382
	private _documents: ExtHostDocuments;
383 384
	private _provider: vscode.OnTypeFormattingEditProvider;

385
	constructor(documents: ExtHostDocuments, provider: vscode.OnTypeFormattingEditProvider) {
386 387 388 389
		this._documents = documents;
		this._provider = provider;
	}

390
	autoFormatTriggerCharacters: string[] = []; // not here
391

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

394
		const { document } = this._documents.getDocumentData(resource);
395
		const pos = TypeConverters.toPosition(position);
396

J
Johannes Rieken 已提交
397
		return asWinJsPromise(token => this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token)).then(value => {
398
			if (Array.isArray(value)) {
399
				return value.map(TypeConverters.TextEdit.from);
400
			}
M
Matt Bierner 已提交
401
			return undefined;
402 403 404 405
		});
	}
}

406
class NavigateTypeAdapter {
407

408 409 410
	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;
411

412
	constructor(provider: vscode.WorkspaceSymbolProvider) {
413 414 415
		this._provider = provider;
	}

416 417
	provideWorkspaceSymbols(search: string): TPromise<IWorkspaceSymbols> {
		const result: IWorkspaceSymbols = IdObject.mixin({ symbols: [] });
418
		return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
419 420
			if (!isFalsyOrEmpty(value)) {
				for (const item of value) {
J
Johannes Rieken 已提交
421 422 423
					if (!item) {
						// drop
						continue;
M
Matt Bierner 已提交
424
					}
J
Johannes Rieken 已提交
425 426 427 428 429 430 431
					if (!item.name) {
						console.warn('INVALID SymbolInformation, lacks name', item);
						continue;
					}
					const symbol = IdObject.mixin(TypeConverters.fromSymbolInformation(item));
					this._symbolCache[symbol._id] = item;
					result.symbols.push(symbol);
432
				}
433
			}
434
		}).then(() => {
435 436 437
			if (result.symbols.length > 0) {
				this._resultCache[result._id] = [result.symbols[0]._id, result.symbols[result.symbols.length - 1]._id];
			}
438
			return result;
439 440
		});
	}
441

442
	resolveWorkspaceSymbol(symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
443 444

		if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
445
			return TPromise.as(symbol);
446 447
		}

448 449 450 451
		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);
452
			});
453
		}
M
Matt Bierner 已提交
454
		return undefined;
455
	}
456 457 458 459 460 461 462 463 464 465

	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];
		}
	}
466 467
}

468
class RenameAdapter {
J
Johannes Rieken 已提交
469

470
	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
471 472
	private _provider: vscode.RenameProvider;

473
	constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) {
J
Johannes Rieken 已提交
474 475 476 477
		this._documents = documents;
		this._provider = provider;
	}

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

480
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
481 482 483 484
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {
			if (!value) {
M
Matt Bierner 已提交
485
				return undefined;
J
Johannes Rieken 已提交
486
			}
487
			return TypeConverters.WorkspaceEdit.from(value);
J
Johannes Rieken 已提交
488 489
		}, err => {
			if (typeof err === 'string') {
490
				return <modes.WorkspaceEdit>{
J
Johannes Rieken 已提交
491 492 493
					edits: undefined,
					rejectReason: err
				};
J
Johannes Rieken 已提交
494 495 496 497 498 499 500 501
			} 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 已提交
502 503 504 505 506
			}
		});
	}
}

507

508
class SuggestAdapter {
509

510 511 512 513
	static supportsResolving(provider: vscode.CompletionItemProvider): boolean {
		return typeof provider.resolveCompletionItem === 'function';
	}

514
	private _documents: ExtHostDocuments;
515
	private _commands: CommandsConverter;
516 517
	private _provider: vscode.CompletionItemProvider;

518 519 520 521
	private _cache = new Map<number, vscode.CompletionItem[]>();
	private _idPool = 0;

	constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) {
522
		this._documents = documents;
523
		this._commands = commands;
524 525 526
		this._provider = provider;
	}

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

529
		const doc = this._documents.getDocumentData(resource).document;
530 531
		const pos = TypeConverters.toPosition(position);

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

536 537 538 539
			const _id = this._idPool++;

			const result: IExtHostSuggestResult = {
				_id,
540 541
				suggestions: [],
			};
542

543
			let list: CompletionList;
544
			if (!value) {
545
				// undefined and null are valid results
M
Matt Bierner 已提交
546
				return undefined;
547 548 549 550

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

551
			} else {
552 553
				list = value;
				result.incomplete = list.isIncomplete;
554
			}
555

556 557 558
			// the default text edit range
			const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos))
				.with({ end: pos });
559

560 561 562 563 564 565
			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);
566 567
				}
			}
568
			this._cache.set(_id, list.items);
569

570
			return result;
571 572 573
		});
	}

574
	resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
575 576

		if (typeof this._provider.resolveCompletionItem !== 'function') {
577 578
			return TPromise.as(suggestion);
		}
579

580 581
		const { _parentId, _id } = (<IExtHostSuggestion>suggestion);
		const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id];
582 583 584
		if (!item) {
			return TPromise.as(suggestion);
		}
585

586
		return asWinJsPromise(token => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
587 588 589 590 591 592 593 594

			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 });
595
			const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
596 597 598 599
			if (newSuggestion) {
				mixin(suggestion, newSuggestion, true);
			}

600
			return suggestion;
601 602
		});
	}
603

604 605 606 607 608
	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 已提交
609
		if (typeof item.label !== 'string' || item.label.length === 0) {
610
			console.warn('INVALID text edit -> must have at least a label');
M
Matt Bierner 已提交
611
			return undefined;
612 613
		}

614 615 616 617
		const result: IExtHostSuggestion = {
			//
			_id,
			_parentId,
618 619 620 621 622 623 624 625 626 627
			//
			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),
628 629
			command: this._commands.toInternal(item.command),
			commitCharacters: item.commitCharacters
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
		};

		// '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 已提交
664
			return undefined;
665 666 667 668
		}

		return result;
	}
669 670
}

A
Alex Dima 已提交
671
class SignatureHelpAdapter {
672

673
	private _documents: ExtHostDocuments;
674 675
	private _provider: vscode.SignatureHelpProvider;

676
	constructor(documents: ExtHostDocuments, provider: vscode.SignatureHelpProvider) {
677 678 679 680
		this._documents = documents;
		this._provider = provider;
	}

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

683
		const doc = this._documents.getDocumentData(resource).document;
684 685 686
		const pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideSignatureHelp(doc, pos, token)).then(value => {
687
			if (value) {
688
				return TypeConverters.SignatureHelp.from(value);
689
			}
M
Matt Bierner 已提交
690
			return undefined;
691 692 693 694
		});
	}
}

J
Johannes Rieken 已提交
695 696 697
class LinkProviderAdapter {

	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
698
	private _heapService: ExtHostHeapService;
J
Johannes Rieken 已提交
699 700
	private _provider: vscode.DocumentLinkProvider;

J
Johannes Rieken 已提交
701
	constructor(documents: ExtHostDocuments, heapService: ExtHostHeapService, provider: vscode.DocumentLinkProvider) {
J
Johannes Rieken 已提交
702
		this._documents = documents;
J
Johannes Rieken 已提交
703
		this._heapService = heapService;
J
Johannes Rieken 已提交
704 705 706 707 708 709 710
		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 已提交
711 712
			if (!Array.isArray(links)) {
				return undefined;
J
Johannes Rieken 已提交
713
			}
J
Johannes Rieken 已提交
714 715 716 717 718 719 720 721
			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 已提交
722 723
		});
	}
724 725

	resolveLink(link: modes.ILink): TPromise<modes.ILink> {
J
Johannes Rieken 已提交
726 727
		if (typeof this._provider.resolveDocumentLink !== 'function') {
			return undefined;
728
		}
J
Johannes Rieken 已提交
729 730 731 732 733 734 735 736 737 738 739 740 741

		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;
		});
742
	}
J
Johannes Rieken 已提交
743 744
}

745 746
class ColorProviderAdapter {

J
Joao Moreno 已提交
747 748 749 750
	constructor(
		private _documents: ExtHostDocuments,
		private _provider: vscode.DocumentColorProvider
	) { }
751

752
	provideColors(resource: URI): TPromise<IRawColorInfo[]> {
753
		const doc = this._documents.getDocumentData(resource).document;
J
Joao Moreno 已提交
754 755 756
		return asWinJsPromise(token => this._provider.provideDocumentColors(doc, token)).then(colors => {
			if (!Array.isArray(colors)) {
				return [];
757 758
			}

J
Joao Moreno 已提交
759 760 761
			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],
762
					range: TypeConverters.fromRange(ci.range)
J
Joao Moreno 已提交
763 764 765 766
				};
			});

			return colorInfos;
767 768
		});
	}
769

770 771 772 773 774 775
	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);
776
		});
777
	}
778 779
}

780
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
781
	| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
782
	| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
783
	| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
J
Johannes Rieken 已提交
784

785
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
J
Johannes Rieken 已提交
786

787
	private static _handlePool: number = 0;
J
Johannes Rieken 已提交
788

789
	private _proxy: MainThreadLanguageFeaturesShape;
790
	private _documents: ExtHostDocuments;
791
	private _commands: ExtHostCommands;
792
	private _heapService: ExtHostHeapService;
793
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
794
	private _adapter = new Map<number, Adapter>();
J
Johannes Rieken 已提交
795

796
	constructor(
797
		mainContext: IMainContext,
798
		documents: ExtHostDocuments,
799
		commands: ExtHostCommands,
J
Johannes Rieken 已提交
800
		heapMonitor: ExtHostHeapService,
801 802
		diagnostics: ExtHostDiagnostics
	) {
803
		this._proxy = mainContext.getProxy(MainContext.MainThreadLanguageFeatures);
804 805
		this._documents = documents;
		this._commands = commands;
806
		this._heapService = heapMonitor;
807
		this._diagnostics = diagnostics;
J
Johannes Rieken 已提交
808 809 810 811
	}

	private _createDisposable(handle: number): Disposable {
		return new Disposable(() => {
J
Johannes Rieken 已提交
812
			this._adapter.delete(handle);
J
Johannes Rieken 已提交
813 814 815 816
			this._proxy.$unregister(handle);
		});
	}

817 818 819 820
	private _nextHandle(): number {
		return ExtHostLanguageFeatures._handlePool++;
	}

821
	private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => TPromise<R>): TPromise<R> {
J
Johannes Rieken 已提交
822
		let adapter = this._adapter.get(handle);
J
Johannes Rieken 已提交
823
		if (!(adapter instanceof ctor)) {
824
			return TPromise.wrapError<R>(new Error('no adapter found'));
J
Johannes Rieken 已提交
825
		}
J
Johannes Rieken 已提交
826
		return callback(<any>adapter);
827 828
	}

J
Johannes Rieken 已提交
829 830 831
	// --- outline

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

838 839
	$provideDocumentSymbols(handle: number, resource: UriComponents): TPromise<modes.SymbolInformation[]> {
		return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource)));
J
Johannes Rieken 已提交
840
	}
841 842 843 844 845

	// --- code lens

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

J
Johannes Rieken 已提交
848
		this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider));
849 850 851 852 853 854 855 856 857
		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;
858 859
	}

860 861
	$provideCodeLenses(handle: number, resource: UriComponents): TPromise<modes.ICodeLensSymbol[]> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource)));
862 863
	}

864 865
	$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(URI.revive(resource), symbol));
J
Johannes Rieken 已提交
866 867 868 869 870 871
	}

	// --- declaration

	registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
872
		this._adapter.set(handle, new DefinitionAdapter(this._documents, provider));
J
Johannes Rieken 已提交
873 874
		this._proxy.$registerDeclaractionSupport(handle, selector);
		return this._createDisposable(handle);
875 876
	}

877 878
	$provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Definition> {
		return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(URI.revive(resource), position));
J
Johannes Rieken 已提交
879
	}
J
Johannes Rieken 已提交
880

M
Matt Bierner 已提交
881
	registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
882 883 884 885 886 887
		const handle = this._nextHandle();
		this._adapter.set(handle, new ImplementationAdapter(this._documents, provider));
		this._proxy.$registerImplementationSupport(handle, selector);
		return this._createDisposable(handle);
	}

888 889
	$provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Definition> {
		return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(URI.revive(resource), position));
890 891
	}

892 893 894 895 896 897 898
	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);
	}

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

J
Johannes Rieken 已提交
903 904
	// --- extra info

905
	registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
J
Johannes Rieken 已提交
906
		const handle = this._nextHandle();
907
		this._adapter.set(handle, new HoverAdapter(this._documents, provider));
A
Alex Dima 已提交
908
		this._proxy.$registerHoverProvider(handle, selector);
J
Johannes Rieken 已提交
909 910 911
		return this._createDisposable(handle);
	}

912 913
	$provideHover(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Hover> {
		return this._withAdapter(handle, HoverAdapter, adpater => adpater.provideHover(URI.revive(resource), position));
J
Johannes Rieken 已提交
914
	}
915

J
Johannes Rieken 已提交
916
	// --- occurrences
917 918 919

	registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
920
		this._adapter.set(handle, new DocumentHighlightAdapter(this._documents, provider));
921
		this._proxy.$registerDocumentHighlightProvider(handle, selector);
922 923 924
		return this._createDisposable(handle);
	}

925 926
	$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.DocumentHighlight[]> {
		return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(URI.revive(resource), position));
927
	}
J
Johannes Rieken 已提交
928 929 930 931 932

	// --- references

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

938 939
	$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]> {
		return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.provideReferences(URI.revive(resource), position, context));
J
Johannes Rieken 已提交
940 941
	}

J
Johannes Rieken 已提交
942 943 944 945
	// --- quick fix

	registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
		const handle = this._nextHandle();
946
		this._adapter.set(handle, new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
J
Johannes Rieken 已提交
947 948 949 950
		this._proxy.$registerQuickFixSupport(handle, selector);
		return this._createDisposable(handle);
	}

951 952
	$provideCodeActions(handle: number, resource: UriComponents, range: IRange): TPromise<modes.CodeAction[]> {
		return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), range));
J
Johannes Rieken 已提交
953
	}
954 955 956 957 958

	// --- formatting

	registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
959
		this._adapter.set(handle, new DocumentFormattingAdapter(this._documents, provider));
960 961 962 963
		this._proxy.$registerDocumentFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

964 965
	$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
		return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(URI.revive(resource), options));
966 967 968 969
	}

	registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
970
		this._adapter.set(handle, new RangeFormattingAdapter(this._documents, provider));
971 972 973 974
		this._proxy.$registerRangeFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

975 976
	$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
		return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(URI.revive(resource), range, options));
977 978 979 980
	}

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

986 987
	$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
		return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.provideOnTypeFormattingEdits(URI.revive(resource), position, ch, options));
988 989
	}

990 991 992 993
	// --- navigate types

	registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
		const handle = this._nextHandle();
994
		this._adapter.set(handle, new NavigateTypeAdapter(provider));
995 996 997 998
		this._proxy.$registerNavigateTypeSupport(handle);
		return this._createDisposable(handle);
	}

999
	$provideWorkspaceSymbols(handle: number, search: string): TPromise<IWorkspaceSymbols> {
1000 1001 1002
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
	}

1003
	$resolveWorkspaceSymbol(handle: number, symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
1004
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol));
1005
	}
J
Johannes Rieken 已提交
1006

1007 1008 1009 1010
	$releaseWorkspaceSymbols(handle: number, id: number) {
		this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.releaseWorkspaceSymbols(id));
	}

J
Johannes Rieken 已提交
1011 1012 1013 1014
	// --- rename

	registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
1015
		this._adapter.set(handle, new RenameAdapter(this._documents, provider));
J
Johannes Rieken 已提交
1016 1017 1018 1019
		this._proxy.$registerRenameSupport(handle, selector);
		return this._createDisposable(handle);
	}

1020 1021
	$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit> {
		return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName));
J
Johannes Rieken 已提交
1022
	}
1023 1024 1025

	// --- suggestion

1026
	registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
1027
		const handle = this._nextHandle();
1028
		this._adapter.set(handle, new SuggestAdapter(this._documents, this._commands.converter, provider));
1029
		this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters, SuggestAdapter.supportsResolving(provider));
1030 1031 1032
		return this._createDisposable(handle);
	}

1033 1034
	$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise<IExtHostSuggestResult> {
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context));
1035 1036
	}

1037 1038
	$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, suggestion));
1039
	}
1040

1041 1042 1043 1044
	$releaseCompletionItems(handle: number, id: number): void {
		this._withAdapter(handle, SuggestAdapter, adapter => adapter.releaseCompletionItems(id));
	}

1045 1046 1047 1048
	// --- parameter hints

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

1054 1055
	$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.SignatureHelp> {
		return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(URI.revive(resource), position));
1056
	}
J
Johannes Rieken 已提交
1057

J
Johannes Rieken 已提交
1058 1059 1060 1061
	// --- links

	registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
		const handle = this._nextHandle();
J
Johannes Rieken 已提交
1062
		this._adapter.set(handle, new LinkProviderAdapter(this._documents, this._heapService, provider));
J
Johannes Rieken 已提交
1063 1064 1065 1066
		this._proxy.$registerDocumentLinkProvider(handle, selector);
		return this._createDisposable(handle);
	}

1067 1068
	$provideDocumentLinks(handle: number, resource: UriComponents): TPromise<modes.ILink[]> {
		return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(URI.revive(resource)));
J
Johannes Rieken 已提交
1069 1070
	}

1071 1072 1073 1074
	$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink> {
		return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link));
	}

1075 1076
	registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
		const handle = this._nextHandle();
1077
		this._adapter.set(handle, new ColorProviderAdapter(this._documents, provider));
1078 1079
		this._proxy.$registerDocumentColorProvider(handle, selector);
		return this._createDisposable(handle);
1080 1081
	}

1082 1083
	$provideDocumentColors(handle: number, resource: UriComponents): TPromise<IRawColorInfo[]> {
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(URI.revive(resource)));
1084 1085
	}

1086 1087
	$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo));
1088 1089
	}

1090
	// --- configuration
J
Johannes Rieken 已提交
1091

1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
	private static _serializeRegExp(regExp: RegExp): ISerializedRegExp {
		if (typeof regExp === 'undefined') {
			return undefined;
		}
		if (regExp === null) {
			return null;
		}
		return {
			pattern: regExp.source,
			flags: (regExp.global ? 'g' : '') + (regExp.ignoreCase ? 'i' : '') + (regExp.multiline ? 'm' : ''),
		};
	}

	private static _serializeIndentationRule(indentationRule: vscode.IndentationRule): ISerializedIndentationRule {
		if (typeof indentationRule === 'undefined') {
			return undefined;
		}
		if (indentationRule === null) {
			return null;
		}
		return {
			decreaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.decreaseIndentPattern),
			increaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.increaseIndentPattern),
			indentNextLinePattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.indentNextLinePattern),
			unIndentedLinePattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.unIndentedLinePattern),
		};
	}

	private static _serializeOnEnterRule(onEnterRule: vscode.OnEnterRule): ISerializedOnEnterRule {
		return {
			beforeText: ExtHostLanguageFeatures._serializeRegExp(onEnterRule.beforeText),
			afterText: ExtHostLanguageFeatures._serializeRegExp(onEnterRule.afterText),
			action: onEnterRule.action
		};
	}

	private static _serializeOnEnterRules(onEnterRules: vscode.OnEnterRule[]): ISerializedOnEnterRule[] {
		if (typeof onEnterRules === 'undefined') {
			return undefined;
		}
		if (onEnterRules === null) {
			return null;
		}
		return onEnterRules.map(ExtHostLanguageFeatures._serializeOnEnterRule);
	}

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

1141 1142 1143
		// 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 已提交
1144
		}
J
Johannes Rieken 已提交
1145

1146 1147 1148 1149 1150 1151
		// word definition
		if (wordPattern) {
			this._documents.setWordDefinitionFor(languageId, wordPattern);
		} else {
			this._documents.setWordDefinitionFor(languageId, null);
		}
1152

1153
		const handle = this._nextHandle();
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
		const serializedConfiguration: ISerializedLanguageConfiguration = {
			comments: configuration.comments,
			brackets: configuration.brackets,
			wordPattern: ExtHostLanguageFeatures._serializeRegExp(configuration.wordPattern),
			indentationRules: ExtHostLanguageFeatures._serializeIndentationRule(configuration.indentationRules),
			onEnterRules: ExtHostLanguageFeatures._serializeOnEnterRules(configuration.onEnterRules),
			__electricCharacterSupport: configuration.__electricCharacterSupport,
			__characterPairSupport: configuration.__characterPairSupport,
		};
		this._proxy.$setLanguageConfiguration(handle, languageId, serializedConfiguration);
1164
		return this._createDisposable(handle);
1165
	}
1166
}