extHostLanguageFeatures.ts 43.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';
M
Matt Bierner 已提交
12
import { Range, Disposable, CompletionList, SnippetString, Color, CodeActionKind } from 'vs/workbench/api/node/extHostTypes';
A
Alex Dima 已提交
13
import { ISingleEditOperation } from 'vs/editor/common/model';
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, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto } 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<SymbolInformationDto[]> {
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(symbol => IdObject.mixin(TypeConverters.fromSymbolInformation(symbol)));
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
export interface CustomCodeAction extends CodeActionDto {
259 260 261 262
	_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 277

	provideCodeActions(resource: URI, range: IRange, context: modes.CodeActionContext): TPromise<CodeActionDto[]> {
J
Johannes Rieken 已提交
278

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

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

M
Matt Bierner 已提交
293 294 295 296
		const codeActionContext: vscode.CodeActionContext = {
			diagnostics: allDiagnostics,
			only: context.only ? new CodeActionKind(context.only) : undefined
		};
297
		return asWinJsPromise(token =>
M
Matt Bierner 已提交
298
			this._provider.provideCodeActions(doc, ran, codeActionContext, token)
299 300
		).then(commandsOrActions => {
			if (isFalsyOrEmpty(commandsOrActions)) {
M
Matt Bierner 已提交
301
				return undefined;
J
Johannes Rieken 已提交
302
			}
303 304 305 306
			const result: CustomCodeAction[] = [];
			for (const candidate of commandsOrActions) {
				if (!candidate) {
					continue;
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),
321
						edit: candidate.edit && TypeConverters.WorkspaceEdit.from(candidate.edit),
M
Matt Bierner 已提交
322
						kind: candidate.kind && candidate.kind.value
323
					});
324
				}
325
			}
326

327
			return result;
J
Johannes Rieken 已提交
328 329
		});
	}
330 331 332 333

	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 已提交
334 335
}

336
class DocumentFormattingAdapter {
337

338
	private _documents: ExtHostDocuments;
339 340
	private _provider: vscode.DocumentFormattingEditProvider;

341
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentFormattingEditProvider) {
342 343 344 345
		this._documents = documents;
		this._provider = provider;
	}

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

348
		const { document } = this._documents.getDocumentData(resource);
349 350

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

359
class RangeFormattingAdapter {
360

361
	private _documents: ExtHostDocuments;
362 363
	private _provider: vscode.DocumentRangeFormattingEditProvider;

364
	constructor(documents: ExtHostDocuments, provider: vscode.DocumentRangeFormattingEditProvider) {
365 366 367 368
		this._documents = documents;
		this._provider = provider;
	}

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

371
		const { document } = this._documents.getDocumentData(resource);
372
		const ran = TypeConverters.toRange(range);
373

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

383
class OnTypeFormattingAdapter {
384

385
	private _documents: ExtHostDocuments;
386 387
	private _provider: vscode.OnTypeFormattingEditProvider;

388
	constructor(documents: ExtHostDocuments, provider: vscode.OnTypeFormattingEditProvider) {
389 390 391 392
		this._documents = documents;
		this._provider = provider;
	}

393
	autoFormatTriggerCharacters: string[] = []; // not here
394

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

397
		const { document } = this._documents.getDocumentData(resource);
398
		const pos = TypeConverters.toPosition(position);
399

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

409
class NavigateTypeAdapter {
410

411 412 413
	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;
414

415
	constructor(provider: vscode.WorkspaceSymbolProvider) {
416 417 418
		this._provider = provider;
	}

419 420
	provideWorkspaceSymbols(search: string): TPromise<WorkspaceSymbolsDto> {
		const result: WorkspaceSymbolsDto = IdObject.mixin({ symbols: [] });
421
		return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
422 423
			if (!isFalsyOrEmpty(value)) {
				for (const item of value) {
J
Johannes Rieken 已提交
424 425 426
					if (!item) {
						// drop
						continue;
M
Matt Bierner 已提交
427
					}
J
Johannes Rieken 已提交
428 429 430 431 432 433 434
					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);
435
				}
436
			}
437
		}).then(() => {
438 439 440
			if (result.symbols.length > 0) {
				this._resultCache[result._id] = [result.symbols[0]._id, result.symbols[result.symbols.length - 1]._id];
			}
441
			return result;
442 443
		});
	}
444

445
	resolveWorkspaceSymbol(symbol: SymbolInformationDto): TPromise<SymbolInformationDto> {
446 447

		if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
448
			return TPromise.as(symbol);
449 450
		}

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

	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];
		}
	}
469 470
}

471 472 473 474
interface RenameProvider2 extends vscode.RenameProvider {
	resolveInitialRenameValue?(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<any>;
}

475
class RenameAdapter {
J
Johannes Rieken 已提交
476

477
	static supportsResolving(provider: RenameProvider2): boolean {
478 479 480
		return typeof provider.resolveInitialRenameValue === 'function';
	}

481
	private _documents: ExtHostDocuments;
482
	private _provider: RenameProvider2;
J
Johannes Rieken 已提交
483

484
	constructor(documents: ExtHostDocuments, provider: RenameProvider2) {
J
Johannes Rieken 已提交
485 486 487 488
		this._documents = documents;
		this._provider = provider;
	}

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

491
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
492 493 494 495
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {
			if (!value) {
M
Matt Bierner 已提交
496
				return undefined;
J
Johannes Rieken 已提交
497
			}
498
			return TypeConverters.WorkspaceEdit.from(value);
J
Johannes Rieken 已提交
499 500
		}, err => {
			if (typeof err === 'string') {
501
				return <modes.WorkspaceEdit>{
J
Johannes Rieken 已提交
502 503 504
					edits: undefined,
					rejectReason: err
				};
J
Johannes Rieken 已提交
505 506 507 508 509 510 511 512
			} 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 已提交
513 514 515
			}
		});
	}
516

517
	resolveInitialRenameValue(resource: URI, position: IPosition): TPromise<modes.RenameInitialValue> {
518 519 520 521 522 523 524 525
		if (typeof this._provider.resolveInitialRenameValue !== 'function') {
			return TPromise.as(undefined);
		}

		let doc = this._documents.getDocumentData(resource).document;
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.resolveInitialRenameValue(doc, pos, token)).then((value) => {
526
			return <modes.RenameInitialValue>{
527 528 529 530 531
				range: TypeConverters.fromRange(value.range),
				text: value.text
			};
		});
	}
J
Johannes Rieken 已提交
532 533
}

534

535
class SuggestAdapter {
536

537 538 539 540
	static supportsResolving(provider: vscode.CompletionItemProvider): boolean {
		return typeof provider.resolveCompletionItem === 'function';
	}

541
	private _documents: ExtHostDocuments;
542
	private _commands: CommandsConverter;
543 544
	private _provider: vscode.CompletionItemProvider;

545 546 547 548
	private _cache = new Map<number, vscode.CompletionItem[]>();
	private _idPool = 0;

	constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) {
549
		this._documents = documents;
550
		this._commands = commands;
551 552 553
		this._provider = provider;
	}

554
	provideCompletionItems(resource: URI, position: IPosition, context: modes.SuggestContext): TPromise<SuggestResultDto> {
555

556
		const doc = this._documents.getDocumentData(resource).document;
557 558
		const pos = TypeConverters.toPosition(position);

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

563 564
			const _id = this._idPool++;

565
			const result: SuggestResultDto = {
566
				_id,
567 568
				suggestions: [],
			};
569

570
			let list: CompletionList;
571
			if (!value) {
572
				// undefined and null are valid results
M
Matt Bierner 已提交
573
				return undefined;
574 575 576 577

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

578
			} else {
579 580
				list = value;
				result.incomplete = list.isIncomplete;
581
			}
582

583
			// the default text edit range
M
Matt Bierner 已提交
584
			const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
585
				.with({ end: pos });
586

587 588 589 590 591 592
			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);
593 594
				}
			}
595
			this._cache.set(_id, list.items);
596

597
			return result;
598 599 600
		});
	}

601
	resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
602 603

		if (typeof this._provider.resolveCompletionItem !== 'function') {
604 605
			return TPromise.as(suggestion);
		}
606

607
		const { _parentId, _id } = (<SuggestionDto>suggestion);
608
		const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id];
609 610 611
		if (!item) {
			return TPromise.as(suggestion);
		}
612

613
		return asWinJsPromise(token => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
614 615 616 617 618 619 620

			if (!resolvedItem) {
				return suggestion;
			}

			const doc = this._documents.getDocumentData(resource).document;
			const pos = TypeConverters.toPosition(position);
M
Matt Bierner 已提交
621
			const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos)).with({ end: pos });
622
			const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
623 624 625 626
			if (newSuggestion) {
				mixin(suggestion, newSuggestion, true);
			}

627
			return suggestion;
628 629
		});
	}
630

631 632 633 634
	releaseCompletionItems(id: number): any {
		this._cache.delete(id);
	}

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

641
		const result: SuggestionDto = {
642 643 644
			//
			_id,
			_parentId,
645 646 647 648 649 650 651 652 653 654
			//
			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),
655 656
			command: this._commands.toInternal(item.command),
			commitCharacters: item.commitCharacters
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
		};

		// '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 已提交
691
			return undefined;
692 693 694 695
		}

		return result;
	}
696 697
}

A
Alex Dima 已提交
698
class SignatureHelpAdapter {
699

700
	private _documents: ExtHostDocuments;
701 702
	private _provider: vscode.SignatureHelpProvider;

703
	constructor(documents: ExtHostDocuments, provider: vscode.SignatureHelpProvider) {
704 705 706 707
		this._documents = documents;
		this._provider = provider;
	}

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

710
		const doc = this._documents.getDocumentData(resource).document;
711 712 713
		const pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideSignatureHelp(doc, pos, token)).then(value => {
714
			if (value) {
715
				return TypeConverters.SignatureHelp.from(value);
716
			}
M
Matt Bierner 已提交
717
			return undefined;
718 719 720 721
		});
	}
}

J
Johannes Rieken 已提交
722 723 724
class LinkProviderAdapter {

	private _documents: ExtHostDocuments;
J
Johannes Rieken 已提交
725
	private _heapService: ExtHostHeapService;
J
Johannes Rieken 已提交
726 727
	private _provider: vscode.DocumentLinkProvider;

J
Johannes Rieken 已提交
728
	constructor(documents: ExtHostDocuments, heapService: ExtHostHeapService, provider: vscode.DocumentLinkProvider) {
J
Johannes Rieken 已提交
729
		this._documents = documents;
J
Johannes Rieken 已提交
730
		this._heapService = heapService;
J
Johannes Rieken 已提交
731 732 733 734 735 736 737
		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 已提交
738 739
			if (!Array.isArray(links)) {
				return undefined;
J
Johannes Rieken 已提交
740
			}
J
Johannes Rieken 已提交
741 742 743 744 745 746 747 748
			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 已提交
749 750
		});
	}
751 752

	resolveLink(link: modes.ILink): TPromise<modes.ILink> {
J
Johannes Rieken 已提交
753 754
		if (typeof this._provider.resolveDocumentLink !== 'function') {
			return undefined;
755
		}
J
Johannes Rieken 已提交
756 757 758 759 760 761 762 763 764 765 766 767 768

		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;
		});
769
	}
J
Johannes Rieken 已提交
770 771
}

772 773
class ColorProviderAdapter {

J
Joao Moreno 已提交
774 775 776 777
	constructor(
		private _documents: ExtHostDocuments,
		private _provider: vscode.DocumentColorProvider
	) { }
778

779
	provideColors(resource: URI): TPromise<IRawColorInfo[]> {
780
		const doc = this._documents.getDocumentData(resource).document;
J
Joao Moreno 已提交
781 782 783
		return asWinJsPromise(token => this._provider.provideDocumentColors(doc, token)).then(colors => {
			if (!Array.isArray(colors)) {
				return [];
784 785
			}

J
Joao Moreno 已提交
786 787 788
			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],
789
					range: TypeConverters.fromRange(ci.range)
J
Joao Moreno 已提交
790 791 792 793
				};
			});

			return colorInfos;
794 795
		});
	}
796

797 798 799 800 801 802
	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);
803
		});
804
	}
805 806
}

807
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
808
	| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
809
	| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
810
	| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
J
Johannes Rieken 已提交
811

812
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
J
Johannes Rieken 已提交
813

814
	private static _handlePool: number = 0;
J
Johannes Rieken 已提交
815

816
	private _proxy: MainThreadLanguageFeaturesShape;
817
	private _documents: ExtHostDocuments;
818
	private _commands: ExtHostCommands;
819
	private _heapService: ExtHostHeapService;
820
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
821
	private _adapter = new Map<number, Adapter>();
J
Johannes Rieken 已提交
822

823
	constructor(
824
		mainContext: IMainContext,
825
		documents: ExtHostDocuments,
826
		commands: ExtHostCommands,
J
Johannes Rieken 已提交
827
		heapMonitor: ExtHostHeapService,
828 829
		diagnostics: ExtHostDiagnostics
	) {
830
		this._proxy = mainContext.getProxy(MainContext.MainThreadLanguageFeatures);
831 832
		this._documents = documents;
		this._commands = commands;
833
		this._heapService = heapMonitor;
834
		this._diagnostics = diagnostics;
J
Johannes Rieken 已提交
835 836 837 838
	}

	private _createDisposable(handle: number): Disposable {
		return new Disposable(() => {
J
Johannes Rieken 已提交
839
			this._adapter.delete(handle);
J
Johannes Rieken 已提交
840 841 842 843
			this._proxy.$unregister(handle);
		});
	}

844 845 846 847
	private _nextHandle(): number {
		return ExtHostLanguageFeatures._handlePool++;
	}

848
	private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => TPromise<R>): TPromise<R> {
J
Johannes Rieken 已提交
849
		let adapter = this._adapter.get(handle);
J
Johannes Rieken 已提交
850
		if (!(adapter instanceof ctor)) {
851
			return TPromise.wrapError<R>(new Error('no adapter found'));
J
Johannes Rieken 已提交
852
		}
J
Johannes Rieken 已提交
853
		return callback(<any>adapter);
854 855
	}

856 857 858 859 860 861
	private _addNewAdapter(adapter: Adapter): number {
		const handle = this._nextHandle();
		this._adapter.set(handle, adapter);
		return handle;
	}

J
Johannes Rieken 已提交
862 863 864
	// --- outline

	registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
865
		const handle = this._addNewAdapter(new OutlineAdapter(this._documents, provider));
866
		this._proxy.$registerOutlineSupport(handle, selector);
J
Johannes Rieken 已提交
867 868 869
		return this._createDisposable(handle);
	}

870
	$provideDocumentSymbols(handle: number, resource: UriComponents): TPromise<SymbolInformationDto[]> {
871
		return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource)));
J
Johannes Rieken 已提交
872
	}
873 874 875 876 877

	// --- code lens

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

J
Johannes Rieken 已提交
880
		this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider));
881 882 883 884 885 886 887 888 889
		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;
890 891
	}

892 893
	$provideCodeLenses(handle: number, resource: UriComponents): TPromise<modes.ICodeLensSymbol[]> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource)));
894 895
	}

896 897
	$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 已提交
898 899 900 901 902
	}

	// --- declaration

	registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
903
		const handle = this._addNewAdapter(new DefinitionAdapter(this._documents, provider));
J
Johannes Rieken 已提交
904 905
		this._proxy.$registerDeclaractionSupport(handle, selector);
		return this._createDisposable(handle);
906 907
	}

908 909
	$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 已提交
910
	}
J
Johannes Rieken 已提交
911

M
Matt Bierner 已提交
912
	registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
913
		const handle = this._addNewAdapter(new ImplementationAdapter(this._documents, provider));
914 915 916 917
		this._proxy.$registerImplementationSupport(handle, selector);
		return this._createDisposable(handle);
	}

918 919
	$provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Definition> {
		return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(URI.revive(resource), position));
920 921
	}

922
	registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
923
		const handle = this._addNewAdapter(new TypeDefinitionAdapter(this._documents, provider));
924 925 926 927
		this._proxy.$registerTypeDefinitionSupport(handle, selector);
		return this._createDisposable(handle);
	}

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

J
Johannes Rieken 已提交
932 933
	// --- extra info

934
	registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
935
		const handle = this._addNewAdapter(new HoverAdapter(this._documents, provider));
A
Alex Dima 已提交
936
		this._proxy.$registerHoverProvider(handle, selector);
J
Johannes Rieken 已提交
937 938 939
		return this._createDisposable(handle);
	}

940 941
	$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 已提交
942
	}
943

J
Johannes Rieken 已提交
944
	// --- occurrences
945 946

	registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
947
		const handle = this._addNewAdapter(new DocumentHighlightAdapter(this._documents, provider));
948
		this._proxy.$registerDocumentHighlightProvider(handle, selector);
949 950 951
		return this._createDisposable(handle);
	}

952 953
	$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.DocumentHighlight[]> {
		return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(URI.revive(resource), position));
954
	}
J
Johannes Rieken 已提交
955 956 957 958

	// --- references

	registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
959
		const handle = this._addNewAdapter(new ReferenceAdapter(this._documents, provider));
J
Johannes Rieken 已提交
960 961 962 963
		this._proxy.$registerReferenceSupport(handle, selector);
		return this._createDisposable(handle);
	}

964 965
	$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 已提交
966 967
	}

J
Johannes Rieken 已提交
968 969 970
	// --- quick fix

	registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
971
		const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
J
Johannes Rieken 已提交
972 973 974 975
		this._proxy.$registerQuickFixSupport(handle, selector);
		return this._createDisposable(handle);
	}

976 977

	$provideCodeActions(handle: number, resource: UriComponents, range: IRange, context: modes.CodeActionContext): TPromise<CodeActionDto[]> {
M
Matt Bierner 已提交
978
		return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), range, context));
J
Johannes Rieken 已提交
979
	}
980 981 982 983

	// --- formatting

	registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
984
		const handle = this._addNewAdapter(new DocumentFormattingAdapter(this._documents, provider));
985 986 987 988
		this._proxy.$registerDocumentFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

989 990
	$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
		return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(URI.revive(resource), options));
991 992 993
	}

	registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
994
		const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider));
995 996 997 998
		this._proxy.$registerRangeFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

999 1000
	$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));
1001 1002 1003
	}

	registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {
1004
		const handle = this._addNewAdapter(new OnTypeFormattingAdapter(this._documents, provider));
1005 1006 1007 1008
		this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters);
		return this._createDisposable(handle);
	}

1009 1010
	$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));
1011 1012
	}

1013 1014 1015
	// --- navigate types

	registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
1016
		const handle = this._addNewAdapter(new NavigateTypeAdapter(provider));
1017 1018 1019 1020
		this._proxy.$registerNavigateTypeSupport(handle);
		return this._createDisposable(handle);
	}

1021
	$provideWorkspaceSymbols(handle: number, search: string): TPromise<WorkspaceSymbolsDto> {
1022 1023 1024
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
	}

1025
	$resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise<SymbolInformationDto> {
1026
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol));
1027
	}
J
Johannes Rieken 已提交
1028

1029 1030 1031 1032
	$releaseWorkspaceSymbols(handle: number, id: number) {
		this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.releaseWorkspaceSymbols(id));
	}

J
Johannes Rieken 已提交
1033 1034
	// --- rename

1035
	registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider, canUseProposedApi = false): vscode.Disposable {
1036
		const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider));
1037
		this._proxy.$registerRenameSupport(handle, selector, canUseProposedApi && RenameAdapter.supportsResolving(provider));
J
Johannes Rieken 已提交
1038 1039 1040
		return this._createDisposable(handle);
	}

1041 1042
	$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 已提交
1043
	}
1044

1045 1046 1047 1048
	$resolveInitialRenameValue(handle: number, resource: URI, position: IPosition): TPromise<modes.RenameInitialValue> {
		return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveInitialRenameValue(resource, position));
	}

1049 1050
	// --- suggestion

1051
	registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
1052
		const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider));
1053
		this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters, SuggestAdapter.supportsResolving(provider));
1054 1055 1056
		return this._createDisposable(handle);
	}

1057
	$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise<SuggestResultDto> {
1058
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context));
1059 1060
	}

1061 1062
	$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));
1063
	}
1064

1065 1066 1067 1068
	$releaseCompletionItems(handle: number, id: number): void {
		this._withAdapter(handle, SuggestAdapter, adapter => adapter.releaseCompletionItems(id));
	}

1069 1070 1071
	// --- parameter hints

	registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable {
1072
		const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider));
A
Alex Dima 已提交
1073
		this._proxy.$registerSignatureHelpProvider(handle, selector, triggerCharacters);
1074 1075 1076
		return this._createDisposable(handle);
	}

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

J
Johannes Rieken 已提交
1081 1082 1083
	// --- links

	registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
1084
		const handle = this._addNewAdapter(new LinkProviderAdapter(this._documents, this._heapService, provider));
J
Johannes Rieken 已提交
1085 1086 1087 1088
		this._proxy.$registerDocumentLinkProvider(handle, selector);
		return this._createDisposable(handle);
	}

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

1093 1094 1095 1096
	$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink> {
		return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link));
	}

1097
	registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
1098
		const handle = this._addNewAdapter(new ColorProviderAdapter(this._documents, provider));
1099 1100
		this._proxy.$registerDocumentColorProvider(handle, selector);
		return this._createDisposable(handle);
1101 1102
	}

1103 1104
	$provideDocumentColors(handle: number, resource: UriComponents): TPromise<IRawColorInfo[]> {
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(URI.revive(resource)));
1105 1106
	}

1107 1108
	$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
		return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo));
1109 1110
	}

1111
	// --- configuration
J
Johannes Rieken 已提交
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 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
	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 已提交
1159
	setLanguageConfiguration(languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
1160
		let { wordPattern } = configuration;
J
Johannes Rieken 已提交
1161

1162 1163 1164
		// 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 已提交
1165
		}
J
Johannes Rieken 已提交
1166

1167 1168 1169 1170 1171 1172
		// word definition
		if (wordPattern) {
			this._documents.setWordDefinitionFor(languageId, wordPattern);
		} else {
			this._documents.setWordDefinitionFor(languageId, null);
		}
1173

1174
		const handle = this._nextHandle();
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
		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);
1185
		return this._createDisposable(handle);
1186
	}
1187
}